# HG changeset patch # User cvs # Date 1186992298 -7200 # Node ID 41ff10fd062f47e781fb6689d3de83889123ffcd # Parent f427b8ec43790ae5a64660396717e5c25ff9d23b Import from CVS: tag r20-4b3 diff -r f427b8ec4379 -r 41ff10fd062f CHANGES-beta --- a/CHANGES-beta Mon Aug 13 10:03:54 2007 +0200 +++ b/CHANGES-beta Mon Aug 13 10:04:58 2007 +0200 @@ -1,4 +1,59 @@ -*- indented-text -*- +to 20.4 beta3 "Altai Mountain" +-- query-replace and query-replace-regexp will only replace the region if the + zmacs region is active. +-- iso-acc.el has been packaged +-- iso-ascii.el has been packaged +-- iso-cvt.el has been packaged +-- iso-insert.el has been packaged +-- iso-swed.el has been packaged +-- iso-syntax.el has been packaged +-- swedish.el has been packaged +-- edebug has been packaged +-- ebuff-menu.el has been packaged +-- echistory.el has been packaged +-- ehelp.el has been packaged +-- electric.el has been packaged +-- helper.el has been packaged +-- arc-mode.el has been packaged +-- ada-stmt.el has been packaged +-- ada-mode.el has been packaged +-- fortran.el has been packaged +-- fortran-misc.el has been packaged +-- f90.el has been packaged +-- ksh-mode.el has been packaged +-- m4-mode.el has been packaged +-- strokes.el has been packaged +-- sh-script.el has been packaged +-- simula.el has been packaged +-- tcl.el has been packaged +-- verilog-mode.el has been packaged +-- view.el has been packaged +-- vrml-mode.el has been packaged +-- whitespace-mode.el has been packaged +-- winmgr-mode.el has been packaged +-- xpm-mode.el has been packaged +-- xrdb-mode.el has been packaged +-- Suppress shadowing message if no shadows were found. +-- Moved dumped lisp into top-level lisp directory +-- bug fixes from Didier Verna, Jens-Ulrik Holger Petersen, Martin Buchholz, + and Tomasz Cholewo. +-- Lazy shot updates from Jan Vroonhof +-- Numerous bug fixes from Hrvoje Niksic +-- Numerous bug fixes from Kyle Jones +-- Mule changes courtesy of MORIOKA Tomohiko +-- speedbar has been packaged (and updated courtesy of Hrvoje Niksic) +-- Initial Native MS Windows support courtesy of Jonathan Harris +-- comint has been packaged +-- pcl-cvs has been packaged +-- cc-mode has been packaged +-- ilisp has been packaged +-- apel has been packaged +-- hyperbole has been packaged +-- eterm has been packaged +-- Elimination of broken VMS code courtesy of Andreas Jaeger +-- Miscellaneous bug fixes + to 20.4 beta2 "Alpine" -- hm--html-mode has been packaged -- viper has been packaged @@ -14,7 +69,7 @@ -- Norwegian tutorial update courtesy of Stig Bjorlykkee -- ediff & viper updates courtesy of Michael Kifer -- Canna & Wnn integrated with LEIM courtesy of Stephen Turnbull --- Berkeley DB 2.x support courtesy of Andreas Jaegar +-- Berkeley DB 2.x support courtesy of Andreas Jaeger -- tm has been packaged -- calendar has been packaged -- Build tweak: finder-inf is not aggressively rebuilt diff -r f427b8ec4379 -r 41ff10fd062f ChangeLog --- a/ChangeLog Mon Aug 13 10:03:54 2007 +0200 +++ b/ChangeLog Mon Aug 13 10:04:58 2007 +0200 @@ -1,6 +1,106 @@ +1997-11-08 SL Baur + + * XEmacs 20.4-beta3 is released. + * XEmacs 20.3-pre2 is released. + +Wed November 05 23:40:00 1997 + + * w32/xemacs.mak: moved building the DOC file to after the .elcs. + +Sun November 01 12:00:00 1997 + + * Files split from nt to new w32 directory: + ChangeLog, README, Todo, paths.h, config.h, inc/*, runemacs.c, + xemacs.mak. + +1997-11-05 Didier Verna + + * configure.in: Added the --site-prefixes options for the configure + script. You give a colon or space separated list of prefixes, and + subdirectories include/ and lib/ will be added with -I and -L. + +1997-11-05 Martin Buchholz > + + * configure.in: AIX + gcc fixes. + - Don't wrap -B. aixflags changed to start_flags. + +1997-11-04 SL Baur + + * lwlib/lwlib-Xm.c(update_one_menu_entry): Add missing variable. + From Skip Montanaro + +1997-11-04 Adrian Aichner + + * etc/TUTORIAL.de: + Updated copyright information. Translated most of the COPYING + section. Translated the <<.*>> didactic line. + +1997-10-22 Adrian Aichner + + * etc/TUTORIAL.de: Fixed two issues reported by + Achim Oppelt + + * etc/TUTORIAL.de: + Manually applied rejected patch hunks from Marc Aurel's patch. + Some more fixes. + + * etc/TUTORIAL.de: + Applied patches supplied by Marc Aurel <4-tea-2@bong.saar.de>. + They fix yet more typos and quite a few awkward sentences. + +1997-10-21 Adrian Aichner + + * etc/TUTORIAL.de: Manually merged a few more corrections by + Carsten Leonhardt + +1997-10-20 Adrian Aichner + + * etc/TUTORIAL.de: + Applied patches from Andreas Jaeger to 1.2, + then merged them with 1.3 via ediff-buffers. + Andreas found some quite nasty typos still and added many missing commas. + + * etc/TUTORIAL.de: Re-fill-ed paragraphs after patching. + + * etc/TUTORIAL.de: Applied the excellent patches courtesy of + Carsten Leonhardt . + +1997-11-03 MORIOKA Tomohiko + + * Delete etc/TUTORIAL.th because Thai is not supported yet. + +1997-11-02 MORIOKA Tomohiko + + * etc/TUTORIAL.ko: Renamed from etc/TUTORIAL.kr to fit with ISO + 639 (two letter language code). + + * etc/TUTORIAL.ja: Renamed from etc/TUTORIAL.jp to fit with ISO + 639 (two letter language code). + +1997-11-02 SL Baur + + * etc/CHARSETS: New file imported from Emacs 20.1. + +1997-11-02 Kyle Jones + + * lwlib/lwlib-Xaw.c (xaw_pop_instance): Don't use parent + window's coordinates and dimensions to center the + dialog box unless its mapped_when_managed property is + true. This should avoid the top level widget that the + HAVE_SESSION code creates, which is unmapped and + useless for this purpose. + +1997-11-01 SL Baur + + * XEmacs 20.3-pre1 is released. + 1997-10-31 SL Baur - * XEmacs 20.4-beta2 + * XEmacs 19.16 is released. + +1997-10-31 SL Baur + + * XEmacs 20.4-beta2 is released. 1997-10-30 SL Baur diff -r f427b8ec4379 -r 41ff10fd062f configure --- a/configure Mon Aug 13 10:03:54 2007 +0200 +++ b/configure Mon Aug 13 10:04:58 2007 +0200 @@ -283,6 +283,9 @@ --cflags=FLAGS Compiler flags. Overrides environment variable CFLAGS. --site-includes=PATH List of directories to search first for header files. --site-libraries=PATH List of directories to search first for libraries. +--site-prefixes=PATH List of directories to search for include/ and lib/ + subdirectories, just after 'site-includes' and + 'site-libraries'. --site-runtime-libraries=PATH List of ALL directories to search for dynamically linked libraries at run time. @@ -583,6 +586,7 @@ x_libraries | \ site_includes | \ site_libraries | \ + site_prefixes | \ site_runtime_libraries ) if test "$valomitted" = "yes" ; then if test "$#" = 0 ; then @@ -810,6 +814,7 @@ case "$site_includes" in *:* ) site_includes="`echo '' $site_includes | sed -e 's/^ //' -e 's/:/ /g'`";; esac case "$site_libraries" in *:* ) site_libraries="`echo '' $site_libraries | sed -e 's/^ //' -e 's/:/ /g'`";; esac +case "$site_prefixes" in *:* ) site_prefixes="`echo '' $site_prefixes | sed -e 's/^ //' -e 's/:/ /g'`";; esac case "$site_runtime_libraries" in *:* ) site_runtime_libraries="`echo '' $site_runtime_libraries | sed -e 's/^ //' -e 's/:/ /g'`";; esac test -n "$with_x" && with_x11="$with_x" @@ -868,7 +873,7 @@ esac echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:872: checking whether ln -s works" >&5 +echo "configure:877: checking whether ln -s works" >&5 rm -f conftestdata if ln -s X conftestdata 2>/dev/null @@ -1045,7 +1050,7 @@ echo "checking "the configuration name"" 1>&6 -echo "configure:1049: checking "the configuration name"" >&5 +echo "configure:1054: checking "the configuration name"" >&5 internal_configuration=`echo $configuration | sed 's/-\(energize\|workshop\)//'` if canonical=`$srcdir/config.sub "$internal_configuration"` ; then : ; else exit $? @@ -1501,7 +1506,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1505: checking for $ac_word" >&5 +echo "configure:1510: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1527,7 +1532,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1531: checking for $ac_word" >&5 +echo "configure:1536: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1572,7 +1577,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1576: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1581: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c xe_cppflags='$CPPFLAGS $c_switch_site $c_switch_machine $c_switch_system $c_switch_x_site $X_CFLAGS' @@ -1584,11 +1589,11 @@ cross_compiling=no cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1608,19 +1613,19 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1612: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1617: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1617: checking whether we are using GNU C" >&5 +echo "configure:1622: checking whether we are using GNU C" >&5 cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1629: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1634,7 +1639,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1638: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1643: checking whether ${CC-cc} accepts -g" >&5 echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then @@ -1663,7 +1668,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1667: checking for $ac_word" >&5 +echo "configure:1672: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1689,7 +1694,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1693: checking for $ac_word" >&5 +echo "configure:1698: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1734,7 +1739,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1738: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1743: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c xe_cppflags='$CPPFLAGS $c_switch_site $c_switch_machine $c_switch_system $c_switch_x_site $X_CFLAGS' @@ -1746,11 +1751,11 @@ cross_compiling=no cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1759: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1770,19 +1775,19 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1774: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1779: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1779: checking whether we are using GNU C" >&5 +echo "configure:1784: checking whether we are using GNU C" >&5 cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1791: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1796,7 +1801,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1800: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1805: checking whether ${CC-cc} accepts -g" >&5 echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then @@ -1825,7 +1830,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1829: checking for $ac_word" >&5 +echo "configure:1834: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1851,7 +1856,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1855: checking for $ac_word" >&5 +echo "configure:1860: checking for $ac_word" >&5 if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1896,7 +1901,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1900: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1905: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c xe_cppflags='$CPPFLAGS $c_switch_site $c_switch_machine $c_switch_system $c_switch_x_site $X_CFLAGS' @@ -1908,11 +1913,11 @@ cross_compiling=no cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1932,19 +1937,19 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1936: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1941: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1941: checking whether we are using GNU C" >&5 +echo "configure:1946: checking whether we are using GNU C" >&5 cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1953: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1958,7 +1963,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1962: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1967: checking whether ${CC-cc} accepts -g" >&5 echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then @@ -1991,7 +1996,7 @@ test -n "$NON_GNU_CPP" -a "$GCC" != "yes" -a -z "$CPP" && CPP="$NON_GNU_CPP" echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1995: checking how to run the C preprocessor" >&5 +echo "configure:2000: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -2004,13 +2009,13 @@ # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2014: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2019: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -2021,13 +2026,13 @@ rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2031: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -2050,9 +2055,9 @@ echo $ac_n "checking for AIX""... $ac_c" 1>&6 -echo "configure:2054: checking for AIX" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext <&6 -echo "configure:2083: checking whether we are using SunPro C" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2101: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* __sunpro_c=yes else @@ -2328,7 +2333,7 @@ ld_switch_system_tmp="$ld_switch_system"; ld_switch_system="" for arg in $ld_switch_system_tmp; do case "$arg" in - -L* | -l* | -R* | -u* | -Wl* | -f* | -B*) ld_switch_system="$ld_switch_system $arg" ;; + -L* | -l* | -R* | -u* | -Wl* | -f*) ld_switch_system="$ld_switch_system $arg" ;; -Xlinker* ) ;; * ) ld_switch_system="$ld_switch_system -Xlinker $arg" ;; esac @@ -2336,7 +2341,7 @@ ld_switch_machine_tmp="$ld_switch_machine"; ld_switch_machine="" for arg in $ld_switch_machine_tmp; do case "$arg" in - -L* | -l* | -R* | -u* | -Wl* | -f* | -B*) ld_switch_machine="$ld_switch_machine $arg" ;; + -L* | -l* | -R* | -u* | -Wl* | -f*) ld_switch_machine="$ld_switch_machine $arg" ;; -Xlinker* ) ;; * ) ld_switch_machine="$ld_switch_machine -Xlinker $arg" ;; esac @@ -2344,7 +2349,7 @@ LDFLAGS_tmp="$LDFLAGS"; LDFLAGS="" for arg in $LDFLAGS_tmp; do case "$arg" in - -L* | -l* | -R* | -u* | -Wl* | -f* | -B*) LDFLAGS="$LDFLAGS $arg" ;; + -L* | -l* | -R* | -u* | -Wl* | -f*) LDFLAGS="$LDFLAGS $arg" ;; -Xlinker* ) ;; * ) LDFLAGS="$LDFLAGS -Xlinker $arg" ;; esac @@ -2352,7 +2357,7 @@ ld_call_shared_tmp="$ld_call_shared"; ld_call_shared="" for arg in $ld_call_shared_tmp; do case "$arg" in - -L* | -l* | -R* | -u* | -Wl* | -f* | -B*) ld_call_shared="$ld_call_shared $arg" ;; + -L* | -l* | -R* | -u* | -Wl* | -f*) ld_call_shared="$ld_call_shared $arg" ;; -Xlinker* ) ;; * ) ld_call_shared="$ld_call_shared -Xlinker $arg" ;; esac @@ -2370,7 +2375,7 @@ fi echo $ac_n "checking for dynodump""... $ac_c" 1>&6 -echo "configure:2374: checking for dynodump" >&5 +echo "configure:2379: checking for dynodump" >&5 if test "$unexec" != "unexsol2.o"; then echo "$ac_t""no" 1>&6 else @@ -2396,7 +2401,7 @@ if test "$unexec" = "unexaix.o"; then start_flags="-Wl,-bnso,-bnodelcsect" - test "$GCC" = "yes" && start_flags="-B/bin/ ${aixflags}" + test "$GCC" = "yes" && start_flags="-B/bin/ ${start_flags}" for f in "/lib/syscalls.exp" "$srcdir/src/m/ibmrs6000.inp"; do if test -r "$f"; then start_flags="${start_flags},-bI:${f}"; fi done @@ -2419,6 +2424,18 @@ + +if test -n "$site_prefixes"; then + for arg in $site_prefixes; do + case "$arg" in + -* ) ;; + * ) argi="-I${arg}/include" ; argl="-L${arg}/lib" ;; + esac + c_switch_site="$c_switch_site $argi" && if test "$extra_verbose" = "yes"; then echo " Appending \"$argi\" to \$c_switch_site"; fi + ld_switch_site="$ld_switch_site $argl" && if test "$extra_verbose" = "yes"; then echo " Appending \"$argl\" to \$ld_switch_site"; fi + done +fi + if test -n "$site_libraries"; then for arg in $site_libraries; do case "$arg" in -* ) ;; * ) arg="-L${arg}" ;; esac @@ -2454,19 +2471,19 @@ if test "$add_runtime_path" = "yes"; then echo $ac_n "checking "for runtime libraries flag"""... $ac_c" 1>&6 -echo "configure:2458: checking "for runtime libraries flag"" >&5 +echo "configure:2475: checking "for runtime libraries flag"" >&5 dash_r="" for try_dash_r in "-R" "-R " "-rpath "; do xe_check_libs="${try_dash_r}/no/such/file-or-directory" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* dash_r="$try_dash_r" else @@ -2564,7 +2581,7 @@ # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2568: checking for $ac_word" >&5 +echo "configure:2585: checking for $ac_word" >&5 if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. @@ -2617,7 +2634,7 @@ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2621: checking for a BSD compatible install" >&5 +echo "configure:2638: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" @@ -2668,7 +2685,7 @@ # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2672: checking for $ac_word" >&5 +echo "configure:2689: checking for $ac_word" >&5 if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. @@ -2699,15 +2716,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2703: checking for $ac_hdr" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2711: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2728: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2740,15 +2757,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2744: checking for $ac_hdr" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2752: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2769: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2781,15 +2798,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2785: checking for $ac_hdr" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2793: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2810: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2819,10 +2836,10 @@ done echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:2823: checking for sys/wait.h that is POSIX.1 compatible" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include @@ -2838,7 +2855,7 @@ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:2842: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2859: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -2862,10 +2879,10 @@ fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2866: checking for ANSI C header files" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include @@ -2873,7 +2890,7 @@ #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2877: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2894: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2890,7 +2907,7 @@ if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2908,7 +2925,7 @@ if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2926,7 +2943,7 @@ if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2937,7 +2954,7 @@ exit (0); } EOF -if { (eval echo configure:2941: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:2958: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then : else @@ -2962,10 +2979,10 @@ fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:2966: checking whether time.h and sys/time.h may both be included" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include @@ -2974,7 +2991,7 @@ struct tm *tp; ; return 0; } EOF -if { (eval echo configure:2978: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2995: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -2998,10 +3015,10 @@ fi echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6 -echo "configure:3002: checking for sys_siglist declaration in signal.h or unistd.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include @@ -3013,7 +3030,7 @@ char *msg = *(sys_siglist + 1); ; return 0; } EOF -if { (eval echo configure:3017: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3034: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_decl_sys_siglist=yes else @@ -3038,9 +3055,9 @@ echo $ac_n "checking for struct utimbuf""... $ac_c" 1>&6 -echo "configure:3042: checking for struct utimbuf" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext < @@ -3059,7 +3076,7 @@ static struct utimbuf x; x.actime = x.modtime; ; return 0; } EOF -if { (eval echo configure:3063: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3080: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -3079,10 +3096,10 @@ rm -f conftest* echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:3083: checking return type of signal handlers" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include @@ -3099,7 +3116,7 @@ int i; ; return 0; } EOF -if { (eval echo configure:3103: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3120: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -3121,10 +3138,10 @@ echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:3125: checking for size_t" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3155,10 +3172,10 @@ fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:3159: checking for pid_t" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3189,10 +3206,10 @@ fi echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:3193: checking for uid_t in sys/types.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF @@ -3228,10 +3245,10 @@ fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 -echo "configure:3232: checking for mode_t" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3262,10 +3279,10 @@ fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:3266: checking for off_t" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3297,9 +3314,9 @@ echo $ac_n "checking for struct timeval""... $ac_c" 1>&6 -echo "configure:3301: checking for struct timeval" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext < @@ -3315,7 +3332,7 @@ static struct timeval x; x.tv_sec = x.tv_usec; ; return 0; } EOF -if { (eval echo configure:3319: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3336: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 HAVE_TIMEVAL=yes @@ -3337,10 +3354,10 @@ rm -f conftest* echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:3341: checking whether struct tm is in sys/time.h or time.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include @@ -3348,7 +3365,7 @@ struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:3352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -3372,10 +3389,10 @@ fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 -echo "configure:3376: checking for tm_zone in struct tm" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #include <$ac_cv_struct_tm> @@ -3383,7 +3400,7 @@ struct tm tm; tm.tm_zone; ; return 0; } EOF -if { (eval echo configure:3387: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3404: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else @@ -3406,10 +3423,10 @@ else echo $ac_n "checking for tzname""... $ac_c" 1>&6 -echo "configure:3410: checking for tzname" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < #ifndef tzname /* For SGI. */ @@ -3419,7 +3436,7 @@ atoi(*tzname); ; return 0; } EOF -if { (eval echo configure:3423: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3440: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_var_tzname=yes else @@ -3445,10 +3462,10 @@ echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:3449: checking for working const" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3518: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -3522,7 +3539,7 @@ echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:3526: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:3543: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` cat > conftestmake <<\EOF @@ -3547,12 +3564,12 @@ echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:3551: checking whether byte ordering is bigendian" >&5 +echo "configure:3568: checking whether byte ordering is bigendian" >&5 ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -3563,11 +3580,11 @@ #endif ; return 0; } EOF -if { (eval echo configure:3567: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3584: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -3578,7 +3595,7 @@ #endif ; return 0; } EOF -if { (eval echo configure:3582: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3599: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -3595,7 +3612,7 @@ rm -f conftest* if test $ac_cv_c_bigendian = unknown; then cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:3629: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_c_bigendian=no else @@ -3634,10 +3651,10 @@ echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:3638: checking size of short" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < main() @@ -3648,7 +3665,7 @@ exit(0); } EOF -if { (eval echo configure:3652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:3669: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_sizeof_short=`cat conftestval` else @@ -3675,10 +3692,10 @@ exit 1 fi echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:3679: checking size of int" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < main() @@ -3689,7 +3706,7 @@ exit(0); } EOF -if { (eval echo configure:3693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:3710: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_sizeof_int=`cat conftestval` else @@ -3710,10 +3727,10 @@ echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:3714: checking size of long" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < main() @@ -3724,7 +3741,7 @@ exit(0); } EOF -if { (eval echo configure:3728: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:3745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_sizeof_long=`cat conftestval` else @@ -3745,10 +3762,10 @@ echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:3749: checking size of long long" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < main() @@ -3759,7 +3776,7 @@ exit(0); } EOF -if { (eval echo configure:3763: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:3780: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_sizeof_long_long=`cat conftestval` else @@ -3780,10 +3797,10 @@ echo $ac_n "checking size of void *""... $ac_c" 1>&6 -echo "configure:3784: checking size of void *" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < main() @@ -3794,7 +3811,7 @@ exit(0); } EOF -if { (eval echo configure:3798: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:3815: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_sizeof_void_p=`cat conftestval` else @@ -3816,7 +3833,7 @@ echo $ac_n "checking for long file names""... $ac_c" 1>&6 -echo "configure:3820: checking for long file names" >&5 +echo "configure:3837: checking for long file names" >&5 ac_cv_sys_long_file_names=yes # Test for long file names in all the places we know might matter: @@ -3863,12 +3880,12 @@ echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6 -echo "configure:3867: checking for sin in -lm" >&5 +echo "configure:3884: checking for sin in -lm" >&5 ac_lib_var=`echo m'_'sin | sed 'y%./+-%__p_%'` xe_check_libs=" -lm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3921,7 +3938,7 @@ echo "checking type of mail spool file locking" 1>&6 -echo "configure:3925: checking type of mail spool file locking" >&5 +echo "configure:3942: checking type of mail spool file locking" >&5 test -z "$mail_locking" -a "$mail_use_flock" = "yes" && mail_locking=flock test -z "$mail_locking" -a "$mail_use_lockf" = "yes" && mail_locking=lockf if test "$mail_locking" = "lockf"; then { test "$extra_verbose" = "yes" && cat << \EOF @@ -3945,12 +3962,12 @@ echo $ac_n "checking for kstat_open in -lkstat""... $ac_c" 1>&6 -echo "configure:3949: checking for kstat_open in -lkstat" >&5 +echo "configure:3966: checking for kstat_open in -lkstat" >&5 ac_lib_var=`echo kstat'_'kstat_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lkstat " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3995,12 +4012,12 @@ echo $ac_n "checking for kvm_read in -lkvm""... $ac_c" 1>&6 -echo "configure:3999: checking for kvm_read in -lkvm" >&5 +echo "configure:4016: checking for kvm_read in -lkvm" >&5 ac_lib_var=`echo kvm'_'kvm_read | sed 'y%./+-%__p_%'` xe_check_libs=" -lkvm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4045,12 +4062,12 @@ echo $ac_n "checking for cma_open in -lpthreads""... $ac_c" 1>&6 -echo "configure:4049: checking for cma_open in -lpthreads" >&5 +echo "configure:4066: checking for cma_open in -lpthreads" >&5 ac_lib_var=`echo pthreads'_'cma_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lpthreads " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4082: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4097,7 +4114,7 @@ fi echo $ac_n "checking whether the -xildoff compiler flag is required""... $ac_c" 1>&6 -echo "configure:4101: checking whether the -xildoff compiler flag is required" >&5 +echo "configure:4118: checking whether the -xildoff compiler flag is required" >&5 if ${CC-cc} '-###' -xildon no_such_file.c 2>&1 | grep '^[^ ]*/ild ' > /dev/null ; then if ${CC-cc} '-###' -xildoff no_such_file.c 2>&1 | grep '^[^ ]*/ild ' > /dev/null ; then echo "$ac_t""no" 1>&6; @@ -4108,7 +4125,7 @@ if test "$opsys" = "sol2" && test "$OS_RELEASE" -ge 56; then echo $ac_n "checking for \"-z ignore\" linker flag""... $ac_c" 1>&6 -echo "configure:4112: checking for \"-z ignore\" linker flag" >&5 +echo "configure:4129: checking for \"-z ignore\" linker flag" >&5 case "`ld -h 2>&1`" in *-z\ ignore\|record* ) echo "$ac_t""yes" 1>&6 ld_switch_site="-z ignore $ld_switch_site" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-z ignore\" to \$ld_switch_site"; fi ;; @@ -4118,7 +4135,7 @@ echo "checking "for specified window system"" 1>&6 -echo "configure:4122: checking "for specified window system"" >&5 +echo "configure:4139: checking "for specified window system"" >&5 if test "$with_x11" != "no"; then test "$x_includes $x_libraries" != "NONE NONE" && \ @@ -4148,7 +4165,7 @@ # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 -echo "configure:4152: checking for X" >&5 +echo "configure:4169: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -4208,12 +4225,12 @@ # First, try using that file with no special directory specified. cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4234: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -4282,14 +4299,14 @@ ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4310: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. @@ -4398,17 +4415,17 @@ case "`(uname -sr) 2>/dev/null`" in "SunOS 5"*) echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 -echo "configure:4402: checking whether -R must be followed by a space" >&5 +echo "configure:4419: checking whether -R must be followed by a space" >&5 ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_R_nospace=yes else @@ -4424,14 +4441,14 @@ else LIBS="$ac_xsave_LIBS -R $x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_R_space=yes else @@ -4467,12 +4484,12 @@ else echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 -echo "configure:4471: checking for dnet_ntoa in -ldnet" >&5 +echo "configure:4488: checking for dnet_ntoa in -ldnet" >&5 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` xe_check_libs=" -ldnet " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4507,12 +4524,12 @@ if test $ac_cv_lib_dnet_dnet_ntoa = no; then echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 -echo "configure:4511: checking for dnet_ntoa in -ldnet_stub" >&5 +echo "configure:4528: checking for dnet_ntoa in -ldnet_stub" >&5 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` xe_check_libs=" -ldnet_stub " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4552,10 +4569,10 @@ # The nsl library prevents programs from opening the X display # on Irix 5.2, according to dickey@clark.net. echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:4556: checking for gethostbyname" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else @@ -4599,12 +4616,12 @@ if test $ac_cv_func_gethostbyname = no; then echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:4603: checking for gethostbyname in -lnsl" >&5 +echo "configure:4620: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` xe_check_libs=" -lnsl " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4636: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4645,10 +4662,10 @@ # -lsocket must be given before -lnsl if both are needed. # We assume that if connect needs -lnsl, so does gethostbyname. echo $ac_n "checking for connect""... $ac_c" 1>&6 -echo "configure:4649: checking for connect" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4692: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_connect=yes" else @@ -4694,12 +4711,12 @@ xe_msg_checking="for connect in -lsocket" test -n "$X_EXTRA_LIBS" && xe_msg_checking="$xe_msg_checking using extra libs $X_EXTRA_LIBS" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:4698: checking "$xe_msg_checking"" >&5 +echo "configure:4715: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` xe_check_libs=" -lsocket $X_EXTRA_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4734,10 +4751,10 @@ # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. echo $ac_n "checking for remove""... $ac_c" 1>&6 -echo "configure:4738: checking for remove" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_remove=yes" else @@ -4781,12 +4798,12 @@ if test $ac_cv_func_remove = no; then echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 -echo "configure:4785: checking for remove in -lposix" >&5 +echo "configure:4802: checking for remove in -lposix" >&5 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` xe_check_libs=" -lposix " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4818: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4821,10 +4838,10 @@ # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. echo $ac_n "checking for shmat""... $ac_c" 1>&6 -echo "configure:4825: checking for shmat" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_shmat=yes" else @@ -4868,12 +4885,12 @@ if test $ac_cv_func_shmat = no; then echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 -echo "configure:4872: checking for shmat in -lipc" >&5 +echo "configure:4889: checking for shmat in -lipc" >&5 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` xe_check_libs=" -lipc " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4905: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -4918,12 +4935,12 @@ # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 -echo "configure:4922: checking for IceConnectionNumber in -lICE" >&5 +echo "configure:4939: checking for IceConnectionNumber in -lICE" >&5 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` xe_check_libs=" -lICE " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5067,7 +5084,7 @@ fi echo "checking for X defines extracted by xmkmf" 1>&6 -echo "configure:5071: checking for X defines extracted by xmkmf" >&5 +echo "configure:5088: checking for X defines extracted by xmkmf" >&5 rm -fr conftestdir if mkdir conftestdir; then cd conftestdir @@ -5099,15 +5116,15 @@ ac_safe=`echo "X11/Intrinsic.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Intrinsic.h""... $ac_c" 1>&6 -echo "configure:5103: checking for X11/Intrinsic.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5128: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -5131,12 +5148,12 @@ echo $ac_n "checking for XOpenDisplay in -lX11""... $ac_c" 1>&6 -echo "configure:5135: checking for XOpenDisplay in -lX11" >&5 +echo "configure:5152: checking for XOpenDisplay in -lX11" >&5 ac_lib_var=`echo X11'_'XOpenDisplay | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5172,12 +5189,12 @@ xe_msg_checking="for XGetFontProperty in -lX11" test -n "-b i486-linuxaout" && xe_msg_checking="$xe_msg_checking using extra libs -b i486-linuxaout" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:5176: checking "$xe_msg_checking"" >&5 +echo "configure:5193: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo X11'_'XGetFontProperty | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 -b i486-linuxaout" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5209: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5215,12 +5232,12 @@ echo $ac_n "checking for XShapeSelectInput in -lXext""... $ac_c" 1>&6 -echo "configure:5219: checking for XShapeSelectInput in -lXext" >&5 +echo "configure:5236: checking for XShapeSelectInput in -lXext" >&5 ac_lib_var=`echo Xext'_'XShapeSelectInput | sed 'y%./+-%__p_%'` xe_check_libs=" -lXext " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5252: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5254,12 +5271,12 @@ echo $ac_n "checking for XtOpenDisplay in -lXt""... $ac_c" 1>&6 -echo "configure:5258: checking for XtOpenDisplay in -lXt" >&5 +echo "configure:5275: checking for XtOpenDisplay in -lXt" >&5 ac_lib_var=`echo Xt'_'XtOpenDisplay | sed 'y%./+-%__p_%'` xe_check_libs=" -lXt " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5291: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5293,14 +5310,14 @@ echo $ac_n "checking the version of X11 being used""... $ac_c" 1>&6 -echo "configure:5297: checking the version of X11 being used" >&5 +echo "configure:5314: checking the version of X11 being used" >&5 cat > conftest.$ac_ext < main(int c, char* v[]) { return c>1 ? XlibSpecificationRelease : 0; } EOF -if { (eval echo configure:5304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:5321: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ./conftest foobar; x11_release=$? else @@ -5324,15 +5341,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5328: checking for $ac_hdr" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5336: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5353: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -5363,7 +5380,7 @@ echo $ac_n "checking for XFree86""... $ac_c" 1>&6 -echo "configure:5367: checking for XFree86" >&5 +echo "configure:5384: checking for XFree86" >&5 if test -d "/usr/X386/include" -o \ -f "/etc/XF86Config" -o \ -f "/etc/X11/XF86Config" -o \ @@ -5383,12 +5400,12 @@ test -z "$with_xmu" && { echo $ac_n "checking for XmuReadBitmapDataFromFile in -lXmu""... $ac_c" 1>&6 -echo "configure:5387: checking for XmuReadBitmapDataFromFile in -lXmu" >&5 +echo "configure:5404: checking for XmuReadBitmapDataFromFile in -lXmu" >&5 ac_lib_var=`echo Xmu'_'XmuReadBitmapDataFromFile | sed 'y%./+-%__p_%'` xe_check_libs=" -lXmu " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5420: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5438,19 +5455,19 @@ echo $ac_n "checking for main in -lXbsd""... $ac_c" 1>&6 -echo "configure:5442: checking for main in -lXbsd" >&5 +echo "configure:5459: checking for main in -lXbsd" >&5 ac_lib_var=`echo Xbsd'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lXbsd " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5471: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5504,7 +5521,7 @@ esac echo "checking for session-management option" 1>&6 -echo "configure:5508: checking for session-management option" >&5; +echo "configure:5525: checking for session-management option" >&5; if test "$with_session" != "no"; then { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_SESSION @@ -5519,15 +5536,15 @@ test -z "$with_xauth" && test "$window_system" = "none" && with_xauth=no test -z "$with_xauth" && { ac_safe=`echo "X11/Xauth.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xauth.h""... $ac_c" 1>&6 -echo "configure:5523: checking for X11/Xauth.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5531: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5548: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -5550,12 +5567,12 @@ } test -z "$with_xauth" && { echo $ac_n "checking for XauGetAuthByAddr in -lXau""... $ac_c" 1>&6 -echo "configure:5554: checking for XauGetAuthByAddr in -lXau" >&5 +echo "configure:5571: checking for XauGetAuthByAddr in -lXau" >&5 ac_lib_var=`echo Xau'_'XauGetAuthByAddr | sed 'y%./+-%__p_%'` xe_check_libs=" -lXau " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5587: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5626,15 +5643,15 @@ for dir in "" "Tt/" "desktop/" ; do ac_safe=`echo "${dir}tt_c.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ${dir}tt_c.h""... $ac_c" 1>&6 -echo "configure:5630: checking for ${dir}tt_c.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5638: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5655: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -5663,12 +5680,12 @@ xe_msg_checking="for tt_message_create in -ltt" test -n "$extra_libs" && xe_msg_checking="$xe_msg_checking using extra libs $extra_libs" echo $ac_n "checking "$xe_msg_checking"""... $ac_c" 1>&6 -echo "configure:5667: checking "$xe_msg_checking"" >&5 +echo "configure:5684: checking "$xe_msg_checking"" >&5 ac_lib_var=`echo tt'_'tt_message_create | sed 'y%./+-%__p_%'` xe_check_libs=" -ltt $extra_libs" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5700: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5728,15 +5745,15 @@ test -z "$with_cde" && { ac_safe=`echo "Dt/Dt.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Dt/Dt.h""... $ac_c" 1>&6 -echo "configure:5732: checking for Dt/Dt.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5740: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5757: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -5759,12 +5776,12 @@ } test -z "$with_cde" && { echo $ac_n "checking for DtDndDragStart in -lDtSvc""... $ac_c" 1>&6 -echo "configure:5763: checking for DtDndDragStart in -lDtSvc" >&5 +echo "configure:5780: checking for DtDndDragStart in -lDtSvc" >&5 ac_lib_var=`echo DtSvc'_'DtDndDragStart | sed 'y%./+-%__p_%'` xe_check_libs=" -lDtSvc " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5796: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5822,19 +5839,19 @@ echo $ac_n "checking for main in -lenergize""... $ac_c" 1>&6 -echo "configure:5826: checking for main in -lenergize" >&5 +echo "configure:5843: checking for main in -lenergize" >&5 ac_lib_var=`echo energize'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lenergize " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5866,19 +5883,19 @@ if test -z "$energize_version"; then echo $ac_n "checking for main in -lconn""... $ac_c" 1>&6 -echo "configure:5870: checking for main in -lconn" >&5 +echo "configure:5887: checking for main in -lconn" >&5 ac_lib_var=`echo conn'_'main | sed 'y%./+-%__p_%'` xe_check_libs=" -lconn " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:5899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -5911,15 +5928,15 @@ fi ac_safe=`echo "editorconn.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for editorconn.h""... $ac_c" 1>&6 -echo "configure:5915: checking for editorconn.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5923: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5940: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -5963,12 +5980,12 @@ if test "$with_x11" = "yes"; then echo "checking for X11 graphics libraries" 1>&6 -echo "configure:5967: checking for X11 graphics libraries" >&5 +echo "configure:5984: checking for X11 graphics libraries" >&5 echo $ac_n "checking for Xpm - no older than 3.4f""... $ac_c" 1>&6 -echo "configure:5969: checking for Xpm - no older than 3.4f" >&5 +echo "configure:5986: checking for Xpm - no older than 3.4f" >&5 xe_check_libs=-lXpm test -z "$with_xpm" && { cat > conftest.$ac_ext < int main(int c, char **v) { @@ -5978,7 +5995,7 @@ 0 ; } EOF -if { (eval echo configure:5982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:5999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ./conftest foobar; xpm_status=$?; if test "$xpm_status" = "0"; then with_xpm=yes; else with_xpm=no; fi; @@ -6016,15 +6033,15 @@ test -z "$with_xface" && { ac_safe=`echo "compface.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for compface.h""... $ac_c" 1>&6 -echo "configure:6020: checking for compface.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6028: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6045: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -6047,12 +6064,12 @@ } test -z "$with_xface" && { echo $ac_n "checking for UnGenFace in -lcompface""... $ac_c" 1>&6 -echo "configure:6051: checking for UnGenFace in -lcompface" >&5 +echo "configure:6068: checking for UnGenFace in -lcompface" >&5 ac_lib_var=`echo compface'_'UnGenFace | sed 'y%./+-%__p_%'` xe_check_libs=" -lcompface " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6084: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6097,17 +6114,17 @@ libs_x="-lcompface $libs_x" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lcompface\" to \$libs_x"; fi fi - test -z "$with_imagick" && { ac_safe=`echo "magick.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for magick.h""... $ac_c" 1>&6 -echo "configure:6103: checking for magick.h" >&5 - -cat > conftest.$ac_ext < + test -z "$with_imagick" && { ac_safe=`echo "magick/magick.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for magick/magick.h""... $ac_c" 1>&6 +echo "configure:6120: checking for magick/magick.h" >&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6128: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -6130,12 +6147,12 @@ } test -z "$with_imagick" && { echo $ac_n "checking for MogrifyImage in -lMagick""... $ac_c" 1>&6 -echo "configure:6134: checking for MogrifyImage in -lMagick" >&5 +echo "configure:6151: checking for MogrifyImage in -lMagick" >&5 ac_lib_var=`echo Magick'_'MogrifyImage | sed 'y%./+-%__p_%'` xe_check_libs=" -lMagick " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6167: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6182,12 +6199,12 @@ echo $ac_n "checking for XawScrollbarSetThumb in -lXaw""... $ac_c" 1>&6 -echo "configure:6186: checking for XawScrollbarSetThumb in -lXaw" >&5 +echo "configure:6203: checking for XawScrollbarSetThumb in -lXaw" >&5 ac_lib_var=`echo Xaw'_'XawScrollbarSetThumb | sed 'y%./+-%__p_%'` xe_check_libs=" -lXaw " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6219: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6222,15 +6239,15 @@ if test "$have_xaw" = "yes"; then ac_safe=`echo "X11/Xaw/Reports.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for X11/Xaw/Reports.h""... $ac_c" 1>&6 -echo "configure:6226: checking for X11/Xaw/Reports.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6234: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6251: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -6256,15 +6273,15 @@ ac_safe=`echo "Xm/Xm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for Xm/Xm.h""... $ac_c" 1>&6 -echo "configure:6260: checking for Xm/Xm.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6268: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6285: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -6281,12 +6298,12 @@ echo "$ac_t""yes" 1>&6 echo $ac_n "checking for XmStringFree in -lXm""... $ac_c" 1>&6 -echo "configure:6285: checking for XmStringFree in -lXm" >&5 +echo "configure:6302: checking for XmStringFree in -lXm" >&5 ac_lib_var=`echo Xm'_'XmStringFree | sed 'y%./+-%__p_%'` xe_check_libs=" -lXm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6553,7 +6570,7 @@ if test "$with_mule" = "yes" ; then echo "checking for Mule-related features" 1>&6 -echo "configure:6557: checking for Mule-related features" >&5 +echo "configure:6574: checking for Mule-related features" >&5 { test "$extra_verbose" = "yes" && cat << \EOF Defining MULE EOF @@ -6570,15 +6587,15 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:6574: checking for $ac_hdr" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6582: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6599: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -6609,12 +6626,12 @@ echo $ac_n "checking for strerror in -lintl""... $ac_c" 1>&6 -echo "configure:6613: checking for strerror in -lintl" >&5 +echo "configure:6630: checking for strerror in -lintl" >&5 ac_lib_var=`echo intl'_'strerror | sed 'y%./+-%__p_%'` xe_check_libs=" -lintl " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6658,19 +6675,19 @@ echo "checking for Mule input methods" 1>&6 -echo "configure:6662: checking for Mule input methods" >&5 +echo "configure:6679: checking for Mule input methods" >&5 test -z "$with_xim" -a "$opsys" != "sol2" && with_xim=no case "$with_xim" in "" | "yes" ) echo "checking for XIM" 1>&6 -echo "configure:6666: checking for XIM" >&5 +echo "configure:6683: checking for XIM" >&5 echo $ac_n "checking for XmImMbLookupString in -lXm""... $ac_c" 1>&6 -echo "configure:6669: checking for XmImMbLookupString in -lXm" >&5 +echo "configure:6686: checking for XmImMbLookupString in -lXm" >&5 ac_lib_var=`echo Xm'_'XmImMbLookupString | sed 'y%./+-%__p_%'` xe_check_libs=" -lXm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6702: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6744,15 +6761,15 @@ fi else case "$with_xfs" in "yes" ) echo "checking for XFontSet" 1>&6 -echo "configure:6748: checking for XFontSet" >&5 +echo "configure:6765: checking for XFontSet" >&5 echo $ac_n "checking for XmbDrawString in -lX11""... $ac_c" 1>&6 -echo "configure:6751: checking for XmbDrawString in -lX11" >&5 +echo "configure:6768: checking for XmbDrawString in -lX11" >&5 ac_lib_var=`echo X11'_'XmbDrawString | sed 'y%./+-%__p_%'` xe_check_libs=" -lX11 " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6784: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6802,15 +6819,15 @@ test "$with_wnn6" = "yes" && with_wnn=yes # wnn6 implies wnn support test -z "$with_wnn" && { ac_safe=`echo "wnn/jllib.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for wnn/jllib.h""... $ac_c" 1>&6 -echo "configure:6806: checking for wnn/jllib.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6831: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -6835,10 +6852,10 @@ for ac_func in crypt do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:6839: checking for $ac_func" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -6890,12 +6907,12 @@ test "$ac_cv_func_crypt" != "yes" && { echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 -echo "configure:6894: checking for crypt in -lcrypt" >&5 +echo "configure:6911: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` xe_check_libs=" -lcrypt " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6927: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6940,12 +6957,12 @@ fi test -z "$with_wnn" && { echo $ac_n "checking for jl_dic_list_e in -lwnn""... $ac_c" 1>&6 -echo "configure:6944: checking for jl_dic_list_e in -lwnn" >&5 +echo "configure:6961: checking for jl_dic_list_e in -lwnn" >&5 ac_lib_var=`echo wnn'_'jl_dic_list_e | sed 'y%./+-%__p_%'` xe_check_libs=" -lwnn " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:6977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6993,12 +7010,12 @@ fi echo $ac_n "checking for jl_fi_dic_list in -lwnn""... $ac_c" 1>&6 -echo "configure:6997: checking for jl_fi_dic_list in -lwnn" >&5 +echo "configure:7014: checking for jl_fi_dic_list in -lwnn" >&5 ac_lib_var=`echo wnn'_'jl_fi_dic_list | sed 'y%./+-%__p_%'` xe_check_libs=" -lwnn " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7041,15 +7058,15 @@ test -z "$with_canna" && { ac_safe=`echo "canna/RK.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for canna/RK.h""... $ac_c" 1>&6 -echo "configure:7045: checking for canna/RK.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7053: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7070: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -7072,12 +7089,12 @@ } test -z "$with_canna" && { echo $ac_n "checking for RkBgnBun in -lRKC""... $ac_c" 1>&6 -echo "configure:7076: checking for RkBgnBun in -lRKC" >&5 +echo "configure:7093: checking for RkBgnBun in -lRKC" >&5 ac_lib_var=`echo RKC'_'RkBgnBun | sed 'y%./+-%__p_%'` xe_check_libs=" -lRKC " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7109: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7111,12 +7128,12 @@ } test -z "$with_canna" && { echo $ac_n "checking for jrKanjiControl in -lcanna""... $ac_c" 1>&6 -echo "configure:7115: checking for jrKanjiControl in -lcanna" >&5 +echo "configure:7132: checking for jrKanjiControl in -lcanna" >&5 ac_lib_var=`echo canna'_'jrKanjiControl | sed 'y%./+-%__p_%'` xe_check_libs=" -lcanna " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7148: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7176,12 +7193,12 @@ libs_x="-lXm $libs_x" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-lXm\" to \$libs_x"; fi echo $ac_n "checking for layout_object_getvalue in -li18n""... $ac_c" 1>&6 -echo "configure:7180: checking for layout_object_getvalue in -li18n" >&5 +echo "configure:7197: checking for layout_object_getvalue in -li18n" >&5 ac_lib_var=`echo i18n'_'layout_object_getvalue | sed 'y%./+-%__p_%'` xe_check_libs=" -li18n " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7213: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -7265,10 +7282,10 @@ for ac_func in acosh asinh atanh cbrt closedir dup2 eaccess fmod fpathconf frexp ftime gethostname getpagesize gettimeofday getcwd getwd logb lrand48 matherr mkdir mktime perror poll random rename res_init rint rmdir select setitimer setpgid setlocale setsid sigblock sighold sigprocmask strcasecmp strerror tzset ulimit usleep utimes waitpid do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7269: checking for $ac_func" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7312: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7321,17 +7338,17 @@ case "$opsys" in - linux* | decosf4-0* | aix4* ) extra_objs="$extra_objs realpath.o" && if test "$extra_verbose" = "yes"; then + linuxaout* | bsdos3* | freebsd* | decosf4-0* | aix4* ) extra_objs="$extra_objs realpath.o" && if test "$extra_verbose" = "yes"; then echo " xemacs will be linked with \"realpath.o\"" fi ;; * ) for ac_func in realpath do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7332: checking for $ac_func" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7375: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7387,16 +7404,16 @@ esac echo $ac_n "checking whether netdb declares h_errno""... $ac_c" 1>&6 -echo "configure:7391: checking whether netdb declares h_errno" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext < int main() { return h_errno; ; return 0; } EOF -if { (eval echo configure:7400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7417: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -7416,16 +7433,16 @@ rm -f conftest* echo $ac_n "checking for sigsetjmp""... $ac_c" 1>&6 -echo "configure:7420: checking for sigsetjmp" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext < int main() { sigjmp_buf bar; sigsetjmp (bar, 0); ; return 0; } EOF -if { (eval echo configure:7429: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7446: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -7445,11 +7462,11 @@ rm -f conftest* echo $ac_n "checking whether localtime caches TZ""... $ac_c" 1>&6 -echo "configure:7449: checking whether localtime caches TZ" >&5 +echo "configure:7466: checking whether localtime caches TZ" >&5 if test "$ac_cv_func_tzset" = "yes"; then cat > conftest.$ac_ext < #if STDC_HEADERS @@ -7484,7 +7501,7 @@ exit (0); } EOF -if { (eval echo configure:7488: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:7505: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then emacs_cv_localtime_cache=no else @@ -7513,9 +7530,9 @@ if test "$HAVE_TIMEVAL" = "yes"; then echo $ac_n "checking whether gettimeofday cannot accept two arguments""... $ac_c" 1>&6 -echo "configure:7517: checking whether gettimeofday cannot accept two arguments" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7558: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* echo "$ac_t""no" 1>&6 else @@ -7558,9 +7575,9 @@ fi echo $ac_n "checking whether the timezone variable is already declared""... $ac_c" 1>&6 -echo "configure:7562: checking whether the timezone variable is already declared" >&5 -cat > conftest.$ac_ext <&5 +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7601: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* echo "$ac_t""yes" 1>&6 { test "$extra_verbose" = "yes" && cat << \EOF @@ -7602,19 +7619,19 @@ echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:7606: checking for inline" >&5 +echo "configure:7623: checking for inline" >&5 ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7635: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -7664,17 +7681,17 @@ # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:7668: checking for working alloca.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:7678: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -7698,10 +7715,10 @@ fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:7702: checking for alloca" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7745: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -7763,10 +7780,10 @@ echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:7767: checking whether alloca needs Cray hooks" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&6 -echo "configure:7794: checking for $ac_func" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:7837: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7846,10 +7863,10 @@ fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:7850: checking stack direction for C alloca" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:7889: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_c_stack_direction=1 else @@ -7896,15 +7913,15 @@ ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for vfork.h""... $ac_c" 1>&6 -echo "configure:7900: checking for vfork.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:7908: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:7925: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -7932,10 +7949,10 @@ fi echo $ac_n "checking for working vfork""... $ac_c" 1>&6 -echo "configure:7936: checking for working vfork" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < @@ -8030,7 +8047,7 @@ } } EOF -if { (eval echo configure:8034: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:8051: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_func_vfork_works=yes else @@ -8055,10 +8072,10 @@ echo $ac_n "checking for working strcoll""... $ac_c" 1>&6 -echo "configure:8059: checking for working strcoll" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < main () @@ -8068,7 +8085,7 @@ strcoll ("123", "456") >= 0); } EOF -if { (eval echo configure:8072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:8089: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_func_strcoll_works=yes else @@ -8095,10 +8112,10 @@ for ac_func in getpgrp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8099: checking for $ac_func" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:8142: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -8149,10 +8166,10 @@ done echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:8153: checking whether getpgrp takes no argument" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:8228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then ac_cv_func_getpgrp_void=yes else @@ -8233,10 +8250,10 @@ echo $ac_n "checking for working mmap""... $ac_c" 1>&6 -echo "configure:8237: checking for working mmap" >&5 +echo "configure:8254: checking for working mmap" >&5 case "$opsys" in ultrix* ) have_mmap=no ;; *) cat > conftest.$ac_ext < #include @@ -8269,7 +8286,7 @@ return 1; } EOF -if { (eval echo configure:8273: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 +if { (eval echo configure:8290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>&5 then have_mmap=yes else @@ -8303,15 +8320,15 @@ ac_safe=`echo "termios.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for termios.h""... $ac_c" 1>&6 -echo "configure:8307: checking for termios.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8315: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8332: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8354,15 +8371,15 @@ echo "$ac_t""no" 1>&6 ac_safe=`echo "termio.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for termio.h""... $ac_c" 1>&6 -echo "configure:8358: checking for termio.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8366: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8383: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8394,10 +8411,10 @@ echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:8398: checking for socket" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:8441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_socket=yes" else @@ -8435,15 +8452,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "netinet/in.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for netinet/in.h""... $ac_c" 1>&6 -echo "configure:8439: checking for netinet/in.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8447: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8464: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8460,15 +8477,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "arpa/inet.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for arpa/inet.h""... $ac_c" 1>&6 -echo "configure:8464: checking for arpa/inet.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8472: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8489: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8493,9 +8510,9 @@ } echo $ac_n "checking "for sun_len member in struct sockaddr_un"""... $ac_c" 1>&6 -echo "configure:8497: checking "for sun_len member in struct sockaddr_un"" >&5 +echo "configure:8514: checking "for sun_len member in struct sockaddr_un"" >&5 cat > conftest.$ac_ext < @@ -8506,7 +8523,7 @@ static struct sockaddr_un x; x.sun_len = 1; ; return 0; } EOF -if { (eval echo configure:8510: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:8527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* echo "$ac_t""yes" 1>&6; { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_SOCKADDR_SUN_LEN @@ -8537,10 +8554,10 @@ echo $ac_n "checking for msgget""... $ac_c" 1>&6 -echo "configure:8541: checking for msgget" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:8584: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_msgget=yes" else @@ -8578,15 +8595,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "sys/ipc.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/ipc.h""... $ac_c" 1>&6 -echo "configure:8582: checking for sys/ipc.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8590: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8607: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8603,15 +8620,15 @@ echo "$ac_t""yes" 1>&6 ac_safe=`echo "sys/msg.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/msg.h""... $ac_c" 1>&6 -echo "configure:8607: checking for sys/msg.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8615: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8632: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8649,15 +8666,15 @@ ac_safe=`echo "dirent.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for dirent.h""... $ac_c" 1>&6 -echo "configure:8653: checking for dirent.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8661: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8678: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8684,15 +8701,15 @@ echo "$ac_t""no" 1>&6 ac_safe=`echo "sys/dir.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/dir.h""... $ac_c" 1>&6 -echo "configure:8688: checking for sys/dir.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8696: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8713: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8725,15 +8742,15 @@ ac_safe=`echo "nlist.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for nlist.h""... $ac_c" 1>&6 -echo "configure:8729: checking for nlist.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8737: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8754: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8763,7 +8780,7 @@ echo "checking "for sound support"" 1>&6 -echo "configure:8767: checking "for sound support"" >&5 +echo "configure:8784: checking "for sound support"" >&5 case "$with_sound" in native | both ) with_native_sound=yes;; nas | no ) with_native_sound=no;; @@ -8774,15 +8791,15 @@ if test -n "$native_sound_lib"; then ac_safe=`echo "multimedia/audio_device.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for multimedia/audio_device.h""... $ac_c" 1>&6 -echo "configure:8778: checking for multimedia/audio_device.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8786: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8803: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -8830,12 +8847,12 @@ if test -z "$native_sound_lib"; then echo $ac_n "checking for ALopenport in -laudio""... $ac_c" 1>&6 -echo "configure:8834: checking for ALopenport in -laudio" >&5 +echo "configure:8851: checking for ALopenport in -laudio" >&5 ac_lib_var=`echo audio'_'ALopenport | sed 'y%./+-%__p_%'` xe_check_libs=" -laudio " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:8867: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -8877,12 +8894,12 @@ if test -z "$native_sound_lib"; then echo $ac_n "checking for AOpenAudio in -lAlib""... $ac_c" 1>&6 -echo "configure:8881: checking for AOpenAudio in -lAlib" >&5 +echo "configure:8898: checking for AOpenAudio in -lAlib" >&5 ac_lib_var=`echo Alib'_'AOpenAudio | sed 'y%./+-%__p_%'` xe_check_libs=" -lAlib " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:8914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -8931,15 +8948,15 @@ for dir in "machine" "sys" "linux"; do ac_safe=`echo "${dir}/soundcard.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ${dir}/soundcard.h""... $ac_c" 1>&6 -echo "configure:8935: checking for ${dir}/soundcard.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:8943: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8960: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -9009,7 +9026,7 @@ fi libs_x="-laudio $libs_x" && if test "$extra_verbose" = "yes"; then echo " Prepending \"-laudio\" to \$libs_x"; fi cat > conftest.$ac_ext < EOF @@ -9036,7 +9053,7 @@ if test "$with_tty" = "yes" ; then echo "checking for TTY-related features" 1>&6 -echo "configure:9040: checking for TTY-related features" >&5 +echo "configure:9057: checking for TTY-related features" >&5 { test "$extra_verbose" = "yes" && cat << \EOF Defining HAVE_TTY EOF @@ -9052,12 +9069,12 @@ if test -z "$with_ncurses"; then echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 -echo "configure:9056: checking for tgetent in -lncurses" >&5 +echo "configure:9073: checking for tgetent in -lncurses" >&5 ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -lncurses " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9089: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9101,15 +9118,15 @@ ac_safe=`echo "ncurses/curses.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ncurses/curses.h""... $ac_c" 1>&6 -echo "configure:9105: checking for ncurses/curses.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9113: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9130: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -9131,15 +9148,15 @@ ac_safe=`echo "ncurses/term.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ncurses/term.h""... $ac_c" 1>&6 -echo "configure:9135: checking for ncurses/term.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9143: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9160: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -9169,15 +9186,15 @@ c_switch_site="$c_switch_site -I/usr/include/ncurses" ac_safe=`echo "ncurses/curses.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ncurses/curses.h""... $ac_c" 1>&6 -echo "configure:9173: checking for ncurses/curses.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9181: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9198: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -9212,12 +9229,12 @@ for lib in curses termlib termcap; do echo $ac_n "checking for tgetent in -l$lib""... $ac_c" 1>&6 -echo "configure:9216: checking for tgetent in -l$lib" >&5 +echo "configure:9233: checking for tgetent in -l$lib" >&5 ac_lib_var=`echo $lib'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -l$lib " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9259,12 +9276,12 @@ else echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 -echo "configure:9263: checking for tgetent in -lcurses" >&5 +echo "configure:9280: checking for tgetent in -lcurses" >&5 ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -lcurses " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9293,12 +9310,12 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 -echo "configure:9297: checking for tgetent in -ltermcap" >&5 +echo "configure:9314: checking for tgetent in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` xe_check_libs=" -ltermcap " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9357,15 +9374,15 @@ test -z "$with_gpm" && { ac_safe=`echo "gpm.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for gpm.h""... $ac_c" 1>&6 -echo "configure:9361: checking for gpm.h" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:9369: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:9386: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -9388,12 +9405,12 @@ } test -z "$with_gpm" && { echo $ac_n "checking for Gpm_Open in -lgpm""... $ac_c" 1>&6 -echo "configure:9392: checking for Gpm_Open in -lgpm" >&5 +echo "configure:9409: checking for Gpm_Open in -lgpm" >&5 ac_lib_var=`echo gpm'_'Gpm_Open | sed 'y%./+-%__p_%'` xe_check_libs=" -lgpm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9425: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9453,17 +9470,17 @@ echo "checking for database support" 1>&6 -echo "configure:9457: checking for database support" >&5 +echo "configure:9474: checking for database support" >&5 if test "$with_database_gnudbm" != "no"; then echo $ac_n "checking for dbm_open in -lgdbm""... $ac_c" 1>&6 -echo "configure:9462: checking for dbm_open in -lgdbm" >&5 +echo "configure:9479: checking for dbm_open in -lgdbm" >&5 ac_lib_var=`echo gdbm'_'dbm_open | sed 'y%./+-%__p_%'` xe_check_libs=" -lgdbm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9496,10 +9513,10 @@ if test "$with_database_gnudbm" != "yes"; then echo $ac_n "checking for dbm_open""... $ac_c" 1>&6 -echo "configure:9500: checking for dbm_open" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_dbm_open=yes" else @@ -9558,10 +9575,10 @@ if test "$with_database_dbm" != "no"; then echo $ac_n "checking for dbm_open""... $ac_c" 1>&6 -echo "configure:9562: checking for dbm_open" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9605: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_dbm_open=yes" else @@ -9605,12 +9622,12 @@ if test "$need_libdbm" != "no"; then echo $ac_n "checking for dbm_open in -ldbm""... $ac_c" 1>&6 -echo "configure:9609: checking for dbm_open in -ldbm" >&5 +echo "configure:9626: checking for dbm_open in -ldbm" >&5 ac_lib_var=`echo dbm'_'dbm_open | sed 'y%./+-%__p_%'` xe_check_libs=" -ldbm " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9642: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9658,10 +9675,10 @@ if test "$with_database_berkdb" != "no"; then echo $ac_n "checking for dbopen""... $ac_c" 1>&6 -echo "configure:9662: checking for dbopen" >&5 - -cat > conftest.$ac_ext <&5 + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9705: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_dbopen=yes" else @@ -9705,12 +9722,12 @@ if test "$need_libdb" != "no"; then echo $ac_n "checking for dbopen in -ldb""... $ac_c" 1>&6 -echo "configure:9709: checking for dbopen in -ldb" >&5 +echo "configure:9726: checking for dbopen in -ldb" >&5 ac_lib_var=`echo db'_'dbopen | sed 'y%./+-%__p_%'` xe_check_libs=" -ldb " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9742: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -9745,7 +9762,7 @@ if test "$with_database_berkdb" = "yes"; then for path in "db/db.h" "db.h"; do cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:9784: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* db_h_path="$path"; break else @@ -9815,12 +9832,12 @@ if test "$with_socks" = "yes"; then echo $ac_n "checking for SOCKSinit in -lsocks""... $ac_c" 1>&6 -echo "configure:9819: checking for SOCKSinit in -lsocks" >&5 +echo "configure:9836: checking for SOCKSinit in -lsocks" >&5 ac_lib_var=`echo socks'_'SOCKSinit | sed 'y%./+-%__p_%'` xe_check_libs=" -lsocks " cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:9852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -10317,6 +10334,9 @@ if test -n "$site_libraries"; then echo " Additional libraries: $site_libraries" fi +if test -n "$site_prefixes"; then + echo " Additional prefixes: $site_prefixes" +fi if test -n "$runpath"; then echo " Runtime library search path: $runpath" fi @@ -10349,7 +10369,7 @@ test "$with_database_berkdb" = yes && echo " Compiling in support for Berkeley DB." test "$with_database_dbm" = yes && echo " Compiling in support for DBM." -test "$with_database_gnudbm" = yes && echo " Compiling in support for GNU DBM." +test "$with_database_gnudbm" = yes && echo " Compiling in support for DBM." test "$with_ncurses" = yes && echo " Compiling in support for ncurses." test "$with_gpm" = yes && echo " Compiling in support for GPM (General Purpose Mouse)." diff -r f427b8ec4379 -r 41ff10fd062f configure.in --- a/configure.in Mon Aug 13 10:03:54 2007 +0200 +++ b/configure.in Mon Aug 13 10:04:58 2007 +0200 @@ -399,6 +399,9 @@ --cflags=FLAGS Compiler flags. Overrides environment variable CFLAGS. --site-includes=PATH List of directories to search first for header files. --site-libraries=PATH List of directories to search first for libraries. +--site-prefixes=PATH List of directories to search for include/ and lib/ + subdirectories, just after 'site-includes' and + 'site-libraries'. --site-runtime-libraries=PATH List of ALL directories to search for dynamically linked libraries at run time. @@ -731,6 +734,7 @@ x_libraries | \ site_includes | \ site_libraries | \ + site_prefixes | \ site_runtime_libraries ) dnl If the value was omitted, get it from the next argument. if test "$valomitted" = "yes" ; then @@ -975,6 +979,7 @@ [case "$[$1]" in *:* [)] [$1]="`echo '' $[$1] | sed -e 's/^ //' -e 's/:/ /g'`";; esac])dnl COLON_TO_SPACE(site_includes) COLON_TO_SPACE(site_libraries) +COLON_TO_SPACE(site_prefixes) COLON_TO_SPACE(site_runtime_libraries) dnl with_x is an obsolete synonym for with_x11 @@ -1894,7 +1899,7 @@ [[$1_tmp]="$[$1]"; [$1]="" for arg in $[$1_tmp]; do case "$arg" in - -L* | -l* | -R* | -u* | -Wl* | -f* | -B*) [$1]="$[$1] $arg" ;; + -L* | -l* | -R* | -u* | -Wl* | -f*) [$1]="$[$1] $arg" ;; -Xlinker* ) ;; * ) [$1]="$[$1] -Xlinker $arg" ;; esac @@ -1934,7 +1939,7 @@ dnl AIX needs various hacks to make static linking work. dnl This can go away if we ever figure out how to get dynamic linking on AIX. start_flags="-Wl,-bnso,-bnodelcsect" - test "$GCC" = "yes" && start_flags="-B/bin/ ${aixflags}" + test "$GCC" = "yes" && start_flags="-B/bin/ ${start_flags}" for f in "/lib/syscalls.exp" "$srcdir/src/m/ibmrs6000.inp"; do if test -r "$f"; then start_flags="${start_flags},-bI:${f}"; fi done @@ -1960,6 +1965,23 @@ dnl Add site and system specific flags to compile and link commands dnl --------------------------------------------------------------- +dnl All dirs present in site-prefixes will be searched for include/ and lib/ +dnl subdirs. This can avoid specifying both site-includes and site-libraries. +dnl Those dirs will take precedence over the standard places, but not over +dnl site-includes and site-libraries. + +dnl --site-prefixes (multiple dirs) +if test -n "$site_prefixes"; then + for arg in $site_prefixes; do + case "$arg" in + -* ) ;; + * ) argi="-I${arg}/include" ; argl="-L${arg}/lib" ;; + esac + XE_APPEND($argi, c_switch_site) + XE_APPEND($argl, ld_switch_site) + done +fi + dnl --site-libraries (multiple dirs) if test -n "$site_libraries"; then for arg in $site_libraries; do @@ -2591,7 +2613,7 @@ fi dnl autodetect ImageMagick - test -z "$with_imagick" && { AC_CHECK_HEADER(magick.h, ,with_imagick=no) } + test -z "$with_imagick" && { AC_CHECK_HEADER(magick/magick.h, ,with_imagick=no) } test -z "$with_imagick" && { AC_CHECK_LIB(Magick, MogrifyImage,[:],with_imagick=no) } test -z "$with_imagick" && with_imagick=yes if test "$with_imagick" = "yes"; then @@ -2795,10 +2817,12 @@ dnl realpath is buggy on linux, decosf and aix4 dnl The realpath() in linux libc (4.6.27) sometimes fails with ELOOP. +dnl The realpath in ELF linux libc's is O.K. dnl For example, call realpath on a file thirty-five or so directories deep dnl and you get ELOOP even if no symlinks at all are involved. +dnl Reports as of 11/1997 indicate BSDi has problems too. case "$opsys" in - linux* | decosf4-0* | aix4* ) XE_ADD_OBJS(realpath.o) ;; + linuxaout* | bsdos3* | freebsd* | decosf4-0* | aix4* ) XE_ADD_OBJS(realpath.o) ;; * ) AC_CHECK_FUNCS(realpath) test "$ac_cv_func_realpath" != "yes" && XE_ADD_OBJS(realpath.o) ;; @@ -3512,6 +3536,9 @@ if test -n "$site_libraries"; then echo " Additional libraries: $site_libraries" fi +if test -n "$site_prefixes"; then + echo " Additional prefixes: $site_prefixes" +fi if test -n "$runpath"; then echo " Runtime library search path: $runpath" fi @@ -3544,7 +3571,7 @@ test "$with_database_berkdb" = yes && echo " Compiling in support for Berkeley DB." test "$with_database_dbm" = yes && echo " Compiling in support for DBM." -test "$with_database_gnudbm" = yes && echo " Compiling in support for GNU DBM." +test "$with_database_gnudbm" = yes && echo " Compiling in support for DBM." test "$with_ncurses" = yes && echo " Compiling in support for ncurses." test "$with_gpm" = yes && echo " Compiling in support for GPM (General Purpose Mouse)." diff -r f427b8ec4379 -r 41ff10fd062f etc/BETA --- a/etc/BETA Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/BETA Mon Aug 13 10:04:58 2007 +0200 @@ -217,9 +217,9 @@ M-x cd to the appropriate directory, and issue the command `C-u M-!' from within XEmacs. -* XEmacs 20.3 packages +* XEmacs 20.4 packages -XEmacs 20.3 has added the concept of installable packages searched prior +XEmacs 20.4 has added the concept of installable packages searched prior to dump time when building. Packages are searched by default under /usr/local/lib/xemacs/packages/. @@ -254,7 +254,7 @@ AUCTeX and Gnus have package tarballs in - ftp://ftp.xemacs.org/pub/beta/packages-20.3/ + ftp://ftp.xemacs.org/pub/beta/xemacs-20.4/packages/ that you can simply untar in a package directory to install. Karl Hegbloom has a set of packages in @@ -265,7 +265,7 @@ ===================================== The packages directory - ftp://ftp.xemacs.org/pub/xemacs/beta/packages-20.3/ + ftp://ftp.xemacs.org/pub/xemacs/beta/xemacs-20.4/packages/ is divided into subdirectory by the major type of package. @@ -294,7 +294,7 @@ ** Binary package installation (binary-packages) ================================================ -Prerequisite: XEmacs 20.3-beta28. +Prerequisite: XEmacs 20.4-b1. Binary packages are complete entities that can be untarred at the top level of an XEmacs package hierarchy and work at runtime. To install files @@ -304,7 +304,7 @@ ** Single file package installation =================================== -Prerequisite: XEmacs 20.3-beta28. +Prerequisite: XEmacs 20.4-b1. These are single file, self-contained lisp packages that don't need a separate directory. To install something from this directory, run diff -r f427b8ec4379 -r 41ff10fd062f etc/CHARSETS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/CHARSETS Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,57 @@ +######################### +## LIST OF CHARSETS +## Each line corresponds to one charset. +## The following attributes are listed in this order +## separated by a colon `:' in one line. +## CHARSET-SYMBOL-NAME, +## CHARSET-ID, +## DIMENSION (1 or 2) +## CHARS (94 or 96) +## BYTES (of multibyte form: 1, 2, 3, or 4), +## WIDTH (occupied column numbers: 1 or 2), +## DIRECTION (0:left-to-right, 1:right-to-left), +## ISO-FINAL-CHAR (character code of ISO-2022's final character) +## ISO-GRAPHIC-PLANE (ISO-2022's graphic plane, 0:GL, 1:GR) +## DESCRIPTION (describing string of the charset) +tibetan-1-column:241:2:94:4:1:0:56:0:Tibetan 1 column glyph +tibetan:252:2:94:4:2:0:55:0:Tibetan characters +lao:167:1:94:3:1:0:49:0:Lao characters (ISO10646 0E80..0EDF) +indian-1-column:240:2:94:4:1:0:54:0:Indian charset for 2-column width glypps +indian-2-column:251:2:94:4:2:0:53:0:Indian charset for 2-column width glyphs +indian-is13194:225:1:94:3:2:0:53:1:Generic Indian charset for data exchange with IS 13194 +ascii-right-to-left:166:1:94:3:1:1:66:0:ASCII (left half of ISO8859-1) with right-to-left direction +chinese-cns11643-7:250:2:94:4:2:0:77:0:CNS11643 Plane 7 Chinese Traditional +chinese-cns11643-6:249:2:94:4:2:0:76:0:CNS11643 Plane 6 Chinese Traditional +chinese-cns11643-5:248:2:94:4:2:0:75:0:CNS11643 Plane 5 Chinese Traditional +chinese-cns11643-4:247:2:94:4:2:0:74:0:CNS11643 Plane 4 Chinese Traditional +chinese-cns11643-3:246:2:94:4:2:0:73:0:CNS11643 Plane 3 Chinese Traditional +ethiopic:245:2:94:4:2:0:51:0:Ethiopic characters +arabic-2-column:224:1:94:3:2:1:52:0:Arabic 2-column +arabic-1-column:165:1:94:3:1:1:51:0:Arabic 1-column +arabic-digit:164:1:94:3:1:0:50:0:Arabic digit +vietnamese-viscii-upper:163:1:96:3:1:0:50:1:VISCII1.1 upper-case +vietnamese-viscii-lower:162:1:96:3:1:0:49:1:VISCII1.1 lower-case +ipa:161:1:96:3:1:0:48:1:IPA (International Phonetic Association) +chinese-sisheng:160:1:94:3:1:0:48:0:SiSheng characters for PinYin/ZhuYin +chinese-big5-2:153:2:94:3:2:0:49:0:Big5 Level-2 Chinese traditional +chinese-big5-1:152:2:94:3:2:0:48:0:Big5 Level-1 Chinese traditional +chinese-cns11643-2:150:2:94:3:2:0:72:0:CNS11643 Plane 2 Chinese traditional +chinese-cns11643-1:149:2:94:3:2:0:71:0:CNS11643 Plane 1 Chinese traditional +japanese-jisx0212:148:2:94:3:2:0:68:0:JISX0212 Japanese supplement +korean-ksc5601:147:2:94:3:2:0:67:0:KSC5601 Korean Hangul and Hanja +japanese-jisx0208:146:2:94:3:2:0:66:0:JISX0208.1983/1990 Japanese Kanji +chinese-gb2312:145:2:94:3:2:0:65:0:GB2312 Chinese simplified +japanese-jisx0208-1978:144:2:94:3:2:0:64:0:JISX0208.1978 Japanese Kanji (so called "old JIS") +latin-iso8859-9:141:1:96:2:1:0:77:1:ISO8859-9 (Latin-5) +cyrillic-iso8859-5:140:1:96:2:1:0:76:1:ISO8859-5 (Cyrillic) +latin-jisx0201:138:1:94:2:1:0:74:0:JISX0201.1976 Japanese Roman +katakana-jisx0201:137:1:94:2:1:0:73:1:JISX0201.1976 Japanese Kana +hebrew-iso8859-8:136:1:96:2:1:1:72:1:ISO8859-8 (Hebrew) +arabic-iso8859-6:135:1:96:2:1:1:71:1:ISO8859-6 (Arabic) +greek-iso8859-7:134:1:96:2:1:0:70:1:ISO8859-7 (Greek) +thai-tis620:133:1:96:2:1:0:84:1:TIS620.2529 (Thai) +latin-iso8859-4:132:1:96:2:1:0:68:1:ISO8859-4 (Latin-4) +latin-iso8859-3:131:1:96:2:1:0:67:1:ISO8859-3 (Latin-3) +latin-iso8859-2:130:1:96:2:1:0:66:1:ISO8859-2 (Latin-2) +latin-iso8859-1:129:1:96:2:1:0:65:1:ISO8859-1 (Latin-1) +ascii:000:1:94:1:1:0:66:0:ASCII (ISO646 IRV) diff -r f427b8ec4379 -r 41ff10fd062f etc/CODINGS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/CODINGS Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,74 @@ +######################### +## LIST OF CODING SYSTEMS +## Each line corresponds to one coding system +## Format of a line is: +## NAME:TYPE:MNEMONIC:EOL:FLAGS:DOCSTRING, +## where +## TYPE = nil (no conversion), t (auto conversion), +## 0 (Mule internal), 1 (SJIS), 2 (ISO2022), 3 (BIG5), or 4 (CCL) +## EOL = 0 (LF), 1 (CRLF), 2 (CR), or 3 (Automatic detection) +## FLAGS = +## if TYPE = 2 then +## comma (`,') separated data of the followings: +## G0, G1, G2, G3, SHORT-FORM, ASCII-EOL, ASCII-CNTL, SEVEN, +## LOCKING-SHIFT, SINGLE-SHIFT, USE-ROMAN, USE-OLDJIS, NO-ISO6429 +## else if TYPE = 4 then +## comma (`,') separated CCL programs for read and write +## else +## 0 +## +no-conversion:nil:=:0:0:Do no conversion +undecided:t:+:3:0:Detect coding-system automatically +hz:0:z:3:0:Codins-system of Hz/ZW used for Chinese (GB). +emacs-mule:0:=:3:0:Internal coding system used in a buffer. +shift_jis:1:S:3:0:Coding-system of Shift-JIS used in Japan. +sjis:1:S:3:0:Coding-system of Shift-JIS used in Japan. +euc-japan-1990:2:E:3:ascii,japanese-jisx0208,katakana-jisx0201,japanese-jisx0212,1,1,1,0,0,1,0,0,0:Coding-system of Japanese EUC (Extended Unix Code). +iso-2022-lock:2:i:3:(ascii,t),-2,-1,-1,0,1,1,1,0,0,0,0,0:ISO-2022 coding system using Locking-Shift for 96-charset. +iso-2022-ss2-7:2:I:3:(ascii,t),-1,-2,-1,1,1,1,1,0,1,0,0,0:ISO-2022 coding system using SS2 for 96-charset in 7-bit code. +iso-2022-ss2-8:2:I:3:(ascii,t),-1,-2,-1,0,1,1,0,0,1,0,0,0:ISO-2022 coding system using SS2 for 96-charset in 8-bit code. +iso-2022-cjk:2:I:3:(ascii,t),(nil,korean-ksc5601,chinese-gb2312,chinese-cns11643-1,t),(nil,chinese-cns11643-2),(nil,chinese-cns11643-3,chinese-cns11643-4,chinese-cns11643-5,chinese-cns11643-6,chinese-cns11643-7),1,1,1,1,1,1,0,0,0:Mixture of ISO-2022-JP, ISO-2022-KR, and ISO-2022-CN +cn-gb-2312:2:C:3:(ascii,t),chinese-gb2312,chinese-sisheng,-1,0,1,1,0,0,1,0,0,0:Coding-system of Chinese EUC (so called GB Encoding). +lao:2:T:3:(ascii,t),(lao,t),-1,-1,0,1,0,0,0,0,0,0,0:Coding-system used for ASCII(MSB=0) & LAO(MSB=1). +iso-2022-jp-1978-irv:2:J:3:(ascii,t),-1,-1,-1,1,1,1,1,0,0,1,1,0:Coding-system used for old jis terminal. +junet:2:J:3:(ascii,t),-1,-1,-1,1,1,1,1,0,0,0,0,0:Coding system based on ISO2022 7-bit encoding. +tis620:2:T:3:(ascii,t),(thai-tis620,t),-1,-1,0,1,0,0,0,0,0,0,0:Coding-system used for ASCII(MSB=0) & TIS620(MSB=1). +euc-japan:2:E:3:ascii,japanese-jisx0208,katakana-jisx0201,japanese-jisx0212,1,1,1,0,0,1,0,0,0:Coding-system of Japanese EUC (Extended Unix Code). +iso-2022-int-1:2:I:3:(ascii,t),(korean-ksc5601,t),-1,-1,1,1,1,1,1,0,0,0,0:ISO-2022-INT-1 +euc-china:2:C:3:(ascii,t),chinese-gb2312,chinese-sisheng,-1,0,1,1,0,0,1,0,0,0:Coding-system of Chinese EUC (so called GB Encoding). +old-jis:2:J:3:(ascii,t),-1,-1,-1,1,1,1,1,0,0,1,1,0:Coding-system used for old jis terminal. +iso-2022-7:2:J:3:(ascii,t),-1,-1,-1,1,1,1,1,0,0,0,0,0:Coding system based on ISO2022 7-bit encoding. +iso-2022-cn:2:C:3:ascii,(nil,chinese-gb2312,chinese-cns11643-1),(nil,chinese-cns11643-2),(nil,chinese-cns11643-3,chinese-cns11643-4,chinese-cns11643-5,chinese-cns11643-6,chinese-cns11643-7),0,1,1,1,1,1,0,0,0:Coding system ISO-2022-CN for Chinese (GB and CNS character sets). +ctext:2:X:3:(ascii,t),(latin-iso8859-1,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-1 Compound Text Encoding. +iso-2022-jp:2:J:3:(ascii,t),-1,-1,-1,1,1,1,1,0,0,0,0,0:Coding system based on ISO2022 7-bit encoding. +iso-2022-kr:2:k:3:ascii,(nil,korean-ksc5601),-1,-1,0,1,1,1,1,0,0,0,0:MIME ISO-2022-KR +iso-2022-cn-ext:2:C:3:ascii,(nil,chinese-gb2312,chinese-cns11643-1),(nil,chinese-cns11643-2),(nil,chinese-cns11643-3,chinese-cns11643-4,chinese-cns11643-5,chinese-cns11643-6,chinese-cns11643-7),0,1,1,1,1,1,0,0,0:Coding system ISO-2022-CN for Chinese (GB and CNS character sets). +iso-8859-1:2:X:3:(ascii,t),(latin-iso8859-1,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-1 Compound Text Encoding. +iso-8859-2:2:2:3:(ascii,t),(latin-iso8859-2,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-2 +iso-8859-3:2:3:3:(ascii,t),(latin-iso8859-3,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-3 +iso-8859-4:2:4:3:(ascii,t),(latin-iso8859-4,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-4 +iso-8859-5:2:5:3:(ascii,t),(cyrillic-iso8859-5,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-5 +iso-8859-7:2:7:3:(ascii,t),(greek-iso8859-7,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-7 +iso-8859-8:2:8:3:(ascii,t),(hebrew-iso8859-8,t),-1,-1,0,1,1,0,0,0,0,0,1:MIME ISO-8859-8 +iso-8859-9:2:9:3:(ascii,t),(latin-iso8859-9,t),-1,-1,0,1,1,0,0,0,0,0,0:MIME ISO-8859-9 +euc-kr:2:K:3:(ascii,t),korean-ksc5601,-1,-1,0,1,1,0,0,0,0,0,0:Coding-system of Korean EUC (Extended Unix Code). +euc-korea:2:K:3:(ascii,t),korean-ksc5601,-1,-1,0,1,1,0,0,0,0,0,0:Coding-system of Korean EUC (Extended Unix Code). +cn-big5:3:B:3:0:Coding-system of BIG5. +big5:3:B:3:0:Coding-system of BIG5. +viscii:4:V:3: 3 106 e ffffff0b 100 0 1 19c6 3 4 19c7 19e7 7 8 9 a b c d e f 10 11 12 13 19d6 15 16 17 18 19db 1a 1b 1c 1d 19dc 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 19d5 19a1 19a2 19a3 19a4 19a5 19a6 19a7 19a8 19a9 19aa 19ab 19ac 19ad 19ae 19af 19b0 19b1 19b2 19b5 19fe 19be 19b6 19b7 19b8 19f6 19f7 19ef 19fc 19fb 19f8 19cf 19f5 1921 1922 1923 1924 1925 1926 1927 1928 1929 192a 192b 192c 192d 192e 192f 1930 1931 1932 19de 19bd 1935 1936 1937 1938 19f1 19d1 19d7 19d8 193d 193e 19df 19e0 19e1 19e2 19e3 19e4 19e5 1946 1947 19e8 19e9 19ea 19eb 19ec 19ed 19ee 194f 19f0 1951 19f2 19f3 19f4 1955 1956 1957 1958 19f9 19fa 195b 195c 19fd 195e 195f 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 196a 196b 196c 196d 196e 196f 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 197a 197b 197c 197d 197e 19e6 fffefd0c 16, 1 121 e 41b 10 80 fffffc07 fffffb0c 41b 15 9a fffff707 fffff60c 881d 12 a2 e 4017 80 ffffef0b 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 0 0 b5 b6 b7 b8 0 0 0 0 bd be 0 0 0 0 0 0 0 c6 c7 0 0 0 0 0 0 0 cf 0 d1 0 0 0 d5 d6 d7 d8 0 0 db dc 0 de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe 0 ffff6d0c 881b 12 a3 e 4017 80 ffff660b 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 0 0 93 96 97 98 0 0 0 0 b4 95 0 0 0 0 0 0 0 2 5 0 0 0 0 0 0 0 9f 0 ba 0 0 0 80 14 bb bc 0 0 19 1e 0 b3 bf c0 c1 c2 c3 c4 c5 ff 6 c8 c9 ca cb cc cd ce 9b d0 b9 d2 d3 d4 a0 99 9a 9e d9 da 9d 9c dd 94 0 fffee40c fffee307 fffee20c 16:Coding-system used for VISCII 1.1. +koi8:4:K:3: 3 106 e ffffff0b 100 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f 20 20 20 e71 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 e21 20 20 20 20 20 20 20 20 20 20 20 20 e6e e50 e51 e66 e54 e55 e64 e53 e65 e58 e59 e5a e5b e5c e5d e5e e5f e6f e60 e61 e62 e63 e56 e52 e6c e6b e57 e68 e6d e69 e67 e6a e4e e30 e31 e46 e34 e35 e44 e33 e45 e38 e39 e3a e3b e3c e3d e3e e3f e4f e40 e41 e42 e43 e36 e32 e4c e4b e37 e48 e4d e49 e47 e4a fffefd0c 16, 1 6e e 41b 15 8c fffffc07 fffffb0c e 4017 a0 fffff70b 60 20 b3 20 20 20 20 20 20 20 20 20 20 20 20 20 20 e1 e2 f7 e7 e4 e5 f6 fa e9 ea eb ec ed ee ef f0 f2 f3 f4 f5 e6 e8 e3 fe fb fd ff f9 f8 fc e0 f1 c1 c2 d7 c7 c4 c5 d6 da c9 ca cb cc cd ce cf d0 d2 d3 d4 d5 c6 c8 c3 de db dd df d9 d8 dc c0 d1 20 a3 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ffff950c 16:Coding-system used for KOI8. +koi8-r:4:K:3: 3 106 e ffffff0b 100 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f 20 20 20 e71 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 e21 20 20 20 20 20 20 20 20 20 20 20 20 e6e e50 e51 e66 e54 e55 e64 e53 e65 e58 e59 e5a e5b e5c e5d e5e e5f e6f e60 e61 e62 e63 e56 e52 e6c e6b e57 e68 e6d e69 e67 e6a e4e e30 e31 e46 e34 e35 e44 e33 e45 e38 e39 e3a e3b e3c e3d e3e e3f e4f e40 e41 e42 e43 e36 e32 e4c e4b e37 e48 e4d e49 e47 e4a fffefd0c 16, 1 6e e 41b 15 8c fffffc07 fffffb0c e 4017 a0 fffff70b 60 20 b3 20 20 20 20 20 20 20 20 20 20 20 20 20 20 e1 e2 f7 e7 e4 e5 f6 fa e9 ea eb ec ed ee ef f0 f2 f3 f4 f5 e6 e8 e3 fe fb fd ff f9 f8 fc e0 f1 c1 c2 d7 c7 c4 c5 d6 da c9 ca cb cc cd ce cf d0 d2 d3 d4 d5 c6 c8 c3 de db dd df d9 d8 dc c0 d1 20 a3 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ffff950c 16:Coding-system used for KOI8. +alternativnyj:4:A:3: 3 106 e ffffff0b 100 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f e30 e31 e32 e33 e34 e35 e36 e37 e38 e39 e3a e3b e3c e3d e3e e3f e40 e41 e42 e43 e44 e45 e46 e47 e48 e49 e4a e4b e4c e4d e4e e4f e50 e51 e52 e53 e54 e55 e56 e57 e58 e59 e5a e5b e5c e5d e5e e5f 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 e60 e61 e62 e63 e64 e65 e66 e67 e68 e69 e6a e6b e6c e6d e6e e6f e21 e71 20 20 20 20 20 20 20 20 20 20 20 20 20 e70 fffefd0c 16, 1 6e e 41b 15 8c fffffc07 fffffb0c e 4017 a0 fffff70b 60 20 f0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef ff f1 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ffff950c 16:Coding-system used for Alternativnyj +vscii:4:V:3: 3 106 e ffffff0b 100 0 19fa 19f8 3 19d7 19d8 19e6 7 8 9 a b c d e f 10 19d1 19df 19cf 19d6 19db 19fd 19dc 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 19e0 19e4 19e3 19e1 19d5 19a3 19a7 19e8 19eb 19a8 19e9 19a9 19ae 19ec 19ef 19ee 19ed 19b8 19f2 19f6 19f5 19f3 19f7 19b5 19b6 19b7 19de 19be 19fe 19f9 19fc 19fb a0 19e5 19e2 19ea 19f4 19bd 19df 19f0 1965 1962 196a 1974 193e 1979 1970 19a2 c0 c1 c2 c3 c4 1960 1964 1963 1961 1955 19c6 1922 1946 1947 1921 19c7 19a1 19a5 19a6 19e7 19a5 19ab 1923 1925 1926 1967 1924 1927 1968 19ac 196b 1928 1969 1929 192b 192c 192d 192a 192e 196c 196f 19ad 19aa 19b0 196e 196d 1938 1972 19b1 1976 1975 1973 1977 1930 1931 1932 192f 1935 1936 1937 195e 193e 197e 1979 19b2 197c 197b 197a 1978 1957 1958 1966 1951 1971 194f 1956 195b 197d 195c 19af fffefd0c 16, 1 121 e 41b 10 80 fffffc07 fffffb0c 41b 15 9a fffff707 fffff60c 881d 12 a2 e 4017 80 ffffef0b 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 be bb c6 ca c7 c8 cb cf d1 d5 d2 d3 d4 d6 e8 e5 e6 e7 0 0 e9 ea eb de 0 0 0 0 0 ed 0 0 0 0 0 0 0 bc bd 0 0 0 0 0 0 0 fa 0 f8 0 0 0 b9 fb f5 f6 0 0 fc fe 0 ec 0 b5 b8 a9 b7 b6 a8 f7 c9 cc d0 aa ce d7 dd dc d8 ae f9 df e3 ab e2 e1 e4 f4 ef f3 f2 f1 fd ee 0 ffff6d0c 881b 12 a3 e 4017 80 ffff660b 80 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 0 0 93 96 97 98 0 0 0 0 b4 95 0 0 0 0 0 0 0 2 5 0 0 0 0 0 0 0 9f 0 ba 0 0 0 80 14 bb bc 0 0 19 1e 0 b3 bf c0 c1 c2 c3 c4 c5 ff 6 c8 c9 ca cb cc cd ce 9b d0 b9 d2 d3 d4 a0 99 9a 9e d9 da 9d 9c dd 94 0 fffee40c fffee307 fffee20c 16:Coding-system used for VSCII-1. +############################ +## LIST OF CODING CATEGORIES (ordered by priority) +## CATEGORY:CODING-SYSTEM +## +coding-category-iso-7:iso-2022-7 +coding-category-iso-8-1:iso-8859-1 +coding-category-iso-8-2:iso-8859-1 +coding-category-iso-else:iso-2022-lock +coding-category-emacs-mule:emacs-mule +coding-category-sjis:sjis +coding-category-big5:big5 +coding-category-binary:no-conversion diff -r f427b8ec4379 -r 41ff10fd062f etc/DISTRIB --- a/etc/DISTRIB Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/DISTRIB Mon Aug 13 10:04:58 2007 +0200 @@ -8,22 +8,22 @@ ftp.xemacs.org is the primary distribution point, but you may find copies of it at other sites as well. Some sites to try include: - ftp://ftp.ai.mit.edu:/pub/xemacs/ - ftp://ftp-digital.cern.ch:/pub/beta/xemacs-20.0/ - ftp://ftp.uu.net:/systems/gnu/xemacs/ - ftp://ftp.sunet.se:/pub/gnu/xemacs/ - ftp://ftp.cenatls.cena.dgac.fr:/pub/Emacs/xemacs/ - ftp://ftp.th-darmstadt.de:/pub/editors/xemacs/ - ftp://sunsite.doc.ic.ac.uk:/gnu/xemacs/ - ftp://ftp.ibp.fr:/pub/emacs/xemacs/ - ftp://uiarchive.cso.uiuc.edu:/pub/packages/xemacs/ - ftp://ftp.technion.ac.il:/pub/unsupported/gnu/xemacs/ - ftp://thphys.irb.hr:/pub/xemacs/ + ftp://ftp2.xemacs.org/pub/xemacs/ + ftp://ftp.ai.mit.edu/pub/xemacs/ + ftp://ftp.uu.net/systems/gnu/xemacs/ + ftp://ftp.sunet.se/pub/gnu/xemacs/ + ftp://ftp.cenatls.cena.dgac.fr/pub/Emacs/xemacs/ + ftp://ftp.th-darmstadt.de/pub/editors/xemacs/ + ftp://sunsite.doc.ic.ac.uk/gnu/xemacs/ + ftp://ftp.ibp.fr/pub/emacs/xemacs/ + ftp://uiarchive.cso.uiuc.edu/pub/packages/xemacs/ + ftp://ftp.technion.ac.il/pub/unsupported/gnu/xemacs/ + ftp://thphys.irb.hr/pub/xemacs/ ftp://sunsite.cnlab-switch.ch/mirror/xemacs/ - ftp://ftp.unicamp.br:/pub/xemacs/ - ftp://ftp.usyd.edu.au:/pub/Xemacs/ + ftp://ftp.unicamp.br/pub/xemacs/ + ftp://ftp.usyd.edu.au/pub/Xemacs/ ftp://ftp.lab.kdd.co.jp/xemacs/ - ftp://SunSITE.sut.ac.jp/pub/archives/xemacs/ + ftp://SunSITE.sut.ac.jp/pub/archives/packages/xemacs/ ftp://sunsite.icm.edu.pl/pub/unix/xemacs The most up-to-date list of distribution sites can always be found on diff -r f427b8ec4379 -r 41ff10fd062f etc/NEWS --- a/etc/NEWS Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/NEWS Mon Aug 13 10:04:58 2007 +0200 @@ -106,6 +106,19 @@ *** More user-level documentation on using Mule. +* Changes in XEmacs 20.4 +======================== + +** An arbitrary keystroke can be generated by entering `C-x @ k + RET' where is a spelled out name of the +desired keysym. For example a sequence: + + C-x @ c C-x @ k b a c k s p a c e RET + +will result in a `C-backspace' keystroke. This feature is especially +useful on terminal emulators having key redefinition capability. + + * Changes in XEmacs 20.3 ======================== @@ -223,6 +236,13 @@ sequence. This feature is especially useful on text terminals where it allows one to enter keystrokes like, e.g., `M-home'. +** An arbitrary keystroke can be generated by entering `C-x @ k + RET'. For example a sequence: + + C-x @ c C-x @ k b a c k s p a c e RET + +will result in a `C-backspace' keystroke even on text terminals. + ** Customize changes. *** Customize has undergone a massive speedup, and should now operate diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL --- a/etc/TUTORIAL Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/TUTORIAL Mon Aug 13 10:04:58 2007 +0200 @@ -19,7 +19,7 @@ Important note: to end the Emacs session, type C-x C-c. (Two characters.) The characters ">>" at the left margin indicate directions for you to try using a command. For instance: -<> +<> >> Now type C-v (View next screen) to move to the next screen. (go ahead, do it by holding down the control key while typing v). From now on, you should do this again whenever you finish diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL.de --- a/etc/TUTORIAL.de Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/TUTORIAL.de Mon Aug 13 10:04:58 2007 +0200 @@ -1,3 +1,5 @@ +Copyright (c) 1997, Adrian Aichner . + Copyright (c) 1985, 1996 Free Software Foundation, Inc. See end for conditions. Du betrachtest das Emacs Tutorial. @@ -21,7 +23,7 @@ Wichtig: Tippe C-x C-c, um die Emacs-Sitzung zu beenden (zwei Zeichen). Die ">>" am linken Seitenrand deuten auf Anweisungen, die Du probieren solltest. so z.B: -<> +<> >> Tippe nun C-v (Betrachte nächste Seite) um die nächste Seite zu betrachten. (Also, halte die CONTROL-Taste gedrückt während Du v tippst.) @@ -1124,12 +1126,18 @@ ANFERTIGEN VON KOPIEN --------------------- -This tutorial descends from a long line of Emacs tutorials -starting with the one written by Stuart Cracraft for the original Emacs. -Ben Wing updated the tutorial for X Windows. +Dieses Tutorial stammt, über eine lange Linie von Emacs Tutorials, von +dem von Stuart Cracraft für den ursprünglichen Emacs geschriebenen ab. +Ben Wing hat das Tutorial für X Windows erweitert. Martin Buchholz +und Hrvoje Niksic haben weitere Korrekturen für XEmacs beigetragen. +Ins Deutsche übertragen wurde es von Adrian Aichner +. -This version of the tutorial, like GNU Emacs, is copyrighted, and -comes with permission to distribute copies on certain conditions: +Diese Version des Tutorials ist, wie GNU Emacs selbst, +urheberrechtlich geschützt und erlaubt die Verteilung von Kopien unter +bestimmten Voraussetzungen: + +Copyright (c) 1997, Adrian Aichner . Copyright (c) 1985, 1996 Free Software Foundation @@ -1144,7 +1152,8 @@ under the above conditions, provided also that they carry prominent notices stating who last altered them. -The conditions for copying Emacs itself are more complex, but in the -same spirit. Please read the file COPYING and then do give copies of -GNU Emacs to your friends. Help stamp out software obstructionism -("ownership") by using, writing, and sharing free software! +Die Bedingungen zum Kopieren von Emacs sind komplexer, entsprechen +aber dem selben Geist. Bitte lies die Datei COPYING und gib doch +Kopien von GNU Emacs an Freunde weiter. Hilf mit bei der Beseitigung +von Software-Verhinderungspolitik ("Besitz") durch das Verwenden, +Schreiben and Weitergeben von kostenloser Software! diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL.fr --- a/etc/TUTORIAL.fr Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/TUTORIAL.fr Mon Aug 13 10:04:58 2007 +0200 @@ -30,8 +30,8 @@ NOTE IMPORTANTE: pour quitter Emacs, tapez C-x C-c (deux caractères). Quand vous trouvez les caractères >> au début d'une ligne, cette ligne -vous donne des directives pour essayer une commande. Par exemple, -<> +vous donne des directives pour essayer une commande. Par exemple: +<> >> Maintenant, tapez C-v («view next screen») pour passer à l'écran suivant. (Faites le vraiment! Maintenez la touche enfoncée et tapez 'v'). À partir de maintenant, refaites la même diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL.hr --- a/etc/TUTORIAL.hr Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/TUTORIAL.hr Mon Aug 13 10:04:58 2007 +0200 @@ -19,7 +19,7 @@ Napomena: za izlazak iz Emacsa, utipkajte C-x C-c. (Dva znaka.) Znakovi ">>" na lijevom rubu naznaèuju uputstva da poku¹ate koristiti neku naredbu. Na primjer: -<> +<> >> Sad utipkajte C-v za pomak na sljedeæi ekran. (samo naprijed, uèinite to tako da dr¾ite tipku control i pritisnite 'v'). Od sad, ovo trebate napraviti kad god zavr¹ite diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL.ja --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/TUTORIAL.ja Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,741 @@ + ============================== + $BF|K\8l(B GNUEMACS(Mule) $BF~LgJT(B + ============================== + +$BCm0U!'(B $B$3$NF~LgJT$O!"!V=,$&$h$j47$l$m!W$r%b%C%H!<$K:n@.$5$l$F$$$^(B + $B$9!#(B">>" $B$+$i;O$^$k9T$O!"$=$N;~2?$r$9$Y$-$+$r;X<($7$F$$$^$9!#(B + + + Mule $B$N%3%^%s%I$rF~NO$9$k$H$-$K$O!"0lHLE*$K%3%s%H%m!<%k!&%-! $B%3%s%H%m!<%k!&%-!<$r2!$7$?$^$^!"(B<$BJ8;z(B>$B%-!<$r2!$7$^$9!#Nc$($P!"(B + C-f $B$O!"%3%s%H%m!<%k!&%-!<$r2!$7$J$,$i(B f $B$N%-!<$r2!$9$3$H$r(B + $B0UL#$7$^$9!#(B +<> + >> $B$=$l$G$O!"(BC-v$B!J(BView Next Screen; $B $B%(%9%1!<%W!&%-!<$r2!$7$F$+$iN%$7!"$=$l$+$i(B<$BJ8;z(B>$B%-!<$r2!$7$^(B + $B$9!#(B + +$BCm0U!'(B <$BJ8;z(B>$B$O!"BgJ8;z$G$b>.J8;z$G$b%3%^%s%I$H$7$F$OF1$80UL#$K$J$j(B + $B$^$9!#%a%?%-!<$,;H$($k$J$i$P(B ESC <$BJ8;z(B> $B$NBe$o$j$K(B M-<$BJ8;z(B> + ($B%a%?%-!<$r2!$7$?$^$^(B<$BJ8;z(B>$B%-!<$r2!$9(B) $B$,;H$($^$9!#(B + +$B=EMW$G$9!'(B Emacs$B$r=*N;$5$;$?$$;~$O!"(BC-x C-c $B$r%?%$%W$7$^$9!#(BEmacs$B$r(Bcsh + $B$+$i5/F0$7$F$$$k>l9g!"%5%9%Z%s%I$9$k!J0l;~E*$K;_$a$k(B)$B$3$H$,(B + $B=PMh$^$9!#(BEmacs$B$r%5%9%Z%s%I$9$k$K$O!"(BC-z$B$r%?%$%W$7$^$9!#(B + + + $B$5$F!"$3$l$+$i$O!"0l2hLLJ,FI$_=*$($?$i!"(BC-v $B$rF~NO$7$F9T$C$F2<$5$$!#(B + + $BA0$N2hLL$H> ESC v $B$H(B C-v $B$r;H$C$F!"A08e$K0\F0$9$k$3$H$r2?2s$+;n$7$F$_$J$5$$!#(B + +$BMWLs(B +==== + $B%U%!%$%k$r2hLLKh$K8+$F9T$/$K$O!"$9!#$3$N$H$-!"85%+!<%=%k$N$"$C$?9T$,(B + $B2hLL$NCf1{$K$/$k$h$&$K$9$k(B + + >> $B:#%+!<%=%k$,$I$3$K$"$k$+!"$=$N6a$/$K$I$s$J%F%-%9%H$,=q$+$l$F$$$k(B + $B$+$r3P$($J$5$$!#(BC-l $B$r%?%$%W$7!"%+!<%=%k$,$I$3$K0\F0$7$?$+!"$=$N(B + $B6a$/$N%F%-%9%H$O$I$&$J$C$?$+$rD4$Y$F$_$J$5$$!#(B + +$B4pK\E*$J%+!<%=%k$N@)8f(B +====================== + + $B2hLLKh$N0\F0$O$G$-$k$h$&$K$J$j$^$7$?!#:#EY$O!"2hLL$NCf$G!"FCDj$N>l=j$K(B +$B0\F0$9$k$?$a$NJ}K!$r21$($^$7$g$&!#$3$l$K$O$$$/$D$+$N$d$jJ}$,$"$j$^$9!#0l$D(B +$B$NJ}K!$O!"A0(B(previous)$B$l!"(BC-p, C-n, C-f,C-b $B$K3d$jEv$F$i$l$F(B +$B$*$j!"8=:_$N>l=j$+$i?7$7$$>l=j$K%+!<%=%k$r0\F0$5$;$^$9!#?^$G=q$1$P!"(B + + + $BA0$N9T!$(BC-p + : + : + $B8e$NJ8;z!$(BC-b .... $B8=:_$N%+!<%=%k0LCV(B .... $B@h$NJ8;z!$(BC-f + : + : + $B$l!"(BPrevious, Next, Backward, Forward $B$NF,J8;z$K$J$C$F(B +$B$$$k$N$G!"21$($d$9$$$G$7$g$&!#$3$l$i$O!"4pK\E*$J%+!<%=%k0\F0%3%^%s%I$G$"$j!"(B +$B$$$D$G$b;H$&$b$N$G$9!#(B + + >> C-n $B$r2?2s$+%?%$%W$7!"!J:#!"$"$J$?$,FI$s$G$$$k!K$3$N9T$^$G%+!<%=(B + $B%k$r0\F0$5$;$J$5$$!#(B + + >> C-f $B$r;H$C$F9T$NCf$[$I$K0\F0$7!"(BC-p $B$G2?9T$+>e$K0\F0$7$F$_$J$5(B + $B$$!#%+!<%=%k$N0LCV$NJQ2=$KCm0U$7$J$5$$!#(B + + >> $B9T$N@hF,$G(B C-b $B$r%?%$%W$7$F$_$J$5$$!#%+!<%=%k$O$I$3$K0\F0$7$^$9$+(B + $B!)$5$i$K$b$&>/$7(B C-b $B$r%?%$%W$7!":#EY$O(B C-f $B$G9TKv$NJ}$KLa$j$J$5(B + $B$$!#%+!<%=%k$,9TKv$r1[$($k$H$I$&$J$j$^$9$+!)(B + + + $B2hLL$N@hF,$dKvHx$r1[$($F%+!<%=%k$r0\F0$5$;$h$&$H$9$k$H!"$=$NJ}8~$K$"$k(B +$B%F%-%9%H$,0\F0$7$FMh$F!"%+!<%=%k$O>o$K2hLLFb$K$"$k$h$&$K$5$l$^$9!#(B + + >> C-n $B$r;H$C$F!"%+!<%=%k$r2hLL$N2> ESC f $B$d(B ESC b $B$r2?2s$+%?%$%W$7$F$_$J$5$$!#(BC-f $B$d(B C-b $B$HJ;MQ$7$F(B + $B$_$J$5$$!#(B + + C-f $B$d(B C-b $B$KBP$9$k!"(BESC f $B$d(B ESC b $B$NN`;w@-$KCmL\$7$^$7$g$&!#B?$/$N(B +$B>l9g!"(BESC <$BJ8;z(B>$B$OJ8=q4X78$N=hM}$K;H$o$l!"0lJ}(BC-<$BJ8;z(B>$B$O$=$l$h$j$b$b$C$H4p(B +$BK\E*$JBP>]!JJ8;z$H$+9T$H$+!K$KBP$9$kA`:n$K;H$o$l$^$9!#(B + + C-a $B$H(B C-e $B$bCN$C$F$$$FJXMx$J%3%^%s%I$G$9!#(BC-a $B$O%+!<%=%k$r9T$N@hF,$K(B +$B0\F0$5$;!"(BC-e $B$O9T$NKvHx$K0\F0$5$;$^$9!#(B + + + >> C-a $B$r#22s!"$=$l$+$i(B C-e $B$r#22sF~NO$7$F$_$J$5$$!#$3$l$i$N%3%^%s%I(B + $B$r#22s0J>e7+JV$7$F$b!"%+!<%=%k$O$=$l0J>e0\F0$7$J$$$3$H$KCm0U!#(B + + $B$"$HFs$D!"4JC1$J%+!<%=%k0\F0%3%^%s%I$,$"$j$^$9!#%U%!%$%k$N@hF,$K0\F0$9(B +$B$k(B ESC < $B$H!"%U%!%$%k$NKvHx$K0\F0$9$k(B ESC > $B$G$9!#(B + + $B%F%-%9%HCf$G%+!<%=%k$NB8:_$9$k0LCV$r!V%]%$%s%H!W$H8F$S$^$9!#8@$$$+$($l(B +$B$P!"%+!<%=%k$O!"%F%-%9%H$N$I$3$K%]%$%s%H$,$"$k$+$r2hLL>e$G<($7$F$$$k$N$G$9!#(B + + $B0J2<$KC1=c$J0\F0A`:n$K$D$$$FMWLs$7$^$9!#$3$N$J$+$K$O!"C18l$d9TC10L$G$N(B +$B0\F0%3%^%s%I$b4^$^$l$F$$$^$9!#(B + + C-f $B0lJ8;z@h$K?J$`(B + C-b $B0lJ8;z8e$KLa$k(B + + ESC f $B0lC18l@h$K?J$`(B + ESC b $B0lC18l8e$KLa$k(B + + C-n $B $B%U%!%$%k$N:G8e$K0\F0(B + + >> $B3F!9$N%3%^%s%I$r;n$7$F$_$J$5$$!#$3$l$i$N%3%^%s%I$O!":G$b$7$P$7$P(B + $B;H$o$l$k$b$N$G$9!#:G8e$NFs$D$G$O!"$3$N>l=j$H$ON%$l$?$H$3$m$K0\F0(B + $B$9$k$N$G!"(B C-v $B$d(B ESC v $B$r;H$C$F$3$3$KLa$C$FMh$k$h$&$K$7$J$5$$!#(B + + Emacs$B$NB>$N%3%^%s%I$HF1MM$K!"$3$l$i$N%3%^%s%I$K$O!"7+$jJV$7$N2s?t$r;X(B +$BDj$9$k0z?t(B $B$rM?$($k$3$H$,$G$-$^$9!#$=$N$?$a$K$O!"%3%^%s%I$rF~NO$9$kA0$K!"(B +C-u$B$KB3$$$F7+$jJV$92s?t$rF~NO$7$^$9!#(B + + $BNc$($P!"(BC-u 8 C-f $B$H$9$k$H!"#8J8;zJ,@h$K0\F0$7$^$9!#(B + + >> C-n $B$"$k$$$O(B C-p $B$KE,Ev$J0z?t$r;XDj$7$F!"0l2s$N0\F0$G$J$k$Y$/$3(B + $B$N9T$N6a$/$KMh$k$h$&$K$7$F$_$J$5$$!#(B + + C-v $B$d(B ESC v $B$K$D$$$F$O>/$70c$$$^$9!#$3$N>l9g!";XDj$5$l$??t$N9T$@$12h(B +$BLL$r0\F0$9$k$3$H$K$J$j$^$9!#(B + + >> C-u 3 C-v $B$HF~NO$7$F$_$J$5$$!#(B + + $B85$KLa$k$K$O!"(BC-u 3 ESC v $B$r;H$($P$h$$$N$G$9!#(B + +$BCf;_%3%^%s%I(B +============ + + C-g $B$H$$$&%3%^%s%I$G!"F~NO$rI,MW$H$9$k$h$&$J%3%^%s%I$rCf;_$9$k$3$H$,(B +$B$G$-$^$9!#Nc$($P!"0z?t$rF~NO$7$F$$$kESCf$d!"#2$D0J>e$N%-!> C-u 100 $B$r%?%$%W$7$F0z?t$r#1#0#0$K@_Dj$7!"(BC-g $B$r%?%$%W$7$J$5$$!#(B + $B$=$N$"$H$G(B C-f $B$r%?%$%W$7$F$_$J$5$$!#2?J8;z0\F0$7$^$7$?$+!)$b$7(B + $B4V0c$C$F(B ESC $B$rF~NO$7$F$7$^$C$?;~$b!"(BC-g $B$rF~NO$9$l$PC$;$^(B + $B$9!#(B + +$B%(%i!<(B +====== + + $B;~$K$O!"(BEmacs$B$G5v$5$l$F$$$J$$A`:n$r$7$F$7$^$&$3$H$,$"$j$^$9!#Nc$($P!"(B +$B%3%^%s%I$NDj5A$5$l$F$$$J$$%3%s%H%m!<%k!&%-!<$rF~NO$7$F$7$^$C$?;~$K$O!"(BEmacs +$B$O%Y%k$rLD$i$7!"$5$i$K!"2hLL$N0lHV2<$K!"2?$,0-$+$C$?$+$rI=<($7$^$9!#(B + + Emacs$B$N%P!<%8%g%s$K$h$C$F$O!"$3$NF~LgJT$K=q$+$l$F$$$k$3$H$rl9g$,$"$jF@$^$9!#$=$NMM$J>l9g$K$O!"%(%i!<%a%C%;!<%8$,I=<($5$l$^$9$+$i!"(B +$B2?$+%+!<%=%k0\F0%-!<$r2!$7$F!"$=$N$l$KBP$7$F%F%-%9%H$r(B +$BI=<($9$k$3$H$,$G$-$^$9!#%X%k%W$d!"4v$D$+$N%3%^%s%I$+$i$N=PNO$rI=<($9$k$?$a(B +$B$K8=$l$?M>J,$J%&%#%s%I%&$r>C$9$?$a$K!"$N%&%#%s%I%&$r>C$7$F!"%+!<%=%k$N$"$k%&%#%s%I%&$r!"2hLLA4BN(B +$B$K9-$2$^$9!#(B + + >> $B%+!<%=%k$r$3$N9T$K;}$C$F$-$F!"(BC-u 0 C-l $B$H%?%$%W$7$^$9!#(B + + >> C-h k C-f $B$H%?%$%W$7$J$5$$!#?7$7$$%&%#%s%I%&$,(B C-f $B%3%^%s%I$N%I%-(B + $B%e%a%s%H$rI=<($9$k$?$a$K8=$l$k$HF1;~$K!"$3$N%&%#%s%I%&$,$I$N$h$&(B + $B$K=L$`$+$r4Q;!$7$J$5$$!#(B + + >> C-x 1$B$H%?%$%W$7$F!"%I%-%e%a%s%H$N8=$o$l$F$$$?%&%#%s%I%&$r>C$7$J$5(B + $B$$!#(B + +$BA^F~$H:o=|(B +========== + + $B%F%-%9%H$r%?%$%W$7$?$1$l$P!"C1$K$=$l$r%?%$%W$9$k$@$1$G9=$$$^$;$s!#L\$K(B +$B8+$($kJ8;z!J(B'A','7','*','$B$"(B'$B$J$I!K$O(BEmacs$B$K$h$C$F%F%-%9%H$G$"$k$H$_$J$5$l!"(B +$B$=$N$^$^A^F~$5$l$^$9!#9T$N=*$o$j$O2~9TJ8;z$GI=$5$l!"$3$l$rF~NO$9$k$K$O(B + $B$r%?%$%W$7$^$9!#(B + + $BD>A0$KF~NO$7$?J8;z$r:o=|$9$k$K$O!"(B $B$rF~NO$7$^$9!#(B $B$O!"(B +$B%-!<%\!<%I$G!V(BDelete$B!W$H=q$$$F$"$k%-!<$r2!$7$FF~NO$7$^$9!#!V(BDelete$B!W$N$+$o(B +$B$j$K!V(BRubout$B!W$H=q$$$F$"$k$+$bCN$l$^$;$s!#$h$j0lHLE*$K$O!"(B $B$O!"8=:_(B +$B%+!<%=%k$N$"$k0LCV$ND>A0$NJ8;z$r:o=|$7$^$9!#(B + + >> $BJ8;z$r$$$/$D$+%?%$%W$7!"$=$l$+$i$=$l$i$r(B $B$r;H$C$F:o=|$7(B + $B$J$5$$!#(B + + >> $B1&%^!<%8%s$r1[$($k$^$G%F%-%9%H$r%?%$%W$7$J$5$$!#%F%-%9%H$,0l9T$N(B + $BI}0J>e$KD9$/$J$k$H!"$=$N9T$O2hLL$+$i$O$_=P$7$F!V7QB3!W$5$l$^$9!#(B + $B1&C<$K$"$k(B'\'$B5-9f$O!"$=$N9T$,7QB3$5$l$F$$$k$3$H$rI=$7$F$$$^$9!#(B + Emacs$B$O!"8=:_JT=8Cf$N0LCV$,8+$($k$h$&$K9T$r%9%/%m!<%k$7$^$9!#2hLL(B + $B$N1&$"$k$$$O:8$NC<$K$"$k(B'\'$B5-9f$O!"$=$NJ}8~$K9T$,$^$@B3$$$F$$$k$3(B + $B$H$rI=$7$F$$$^$9!#(B + + $B$3$l$O!"J8>O$G@bL@$9$k$h$j> $B@h$[$IF~NO$7$?!"7QB3$5$l$?9T$N>e$K%+!<%=%k$r$b$C$F$$$-!"(BC-d $B$G%F(B + $B%-%9%H$r:o=|$7$F!"%F%-%9%H$,0l9T$K<}$^$k$h$&$K$7$F$_$J$5$$!#7QB3(B + $B$rI=$9(B'\'$B5-9f$O>C$($^$7$?$M!#(B + + >> $B%+!<%=%k$r9T$N@hF,$K0\F0$7!"(B $B$rF~NO$7$J$5$$!#$3$l$O$=$N9T(B + $B$ND>A0$N9T6g@Z$j$r:o=|$9$k$N$G!"$=$N9T$,A0$N9T$H$D$J$,$C$F$7$^$$(B + $B$^$9!#$D$J$,$C$?9T$,2hLL$NI}$h$jD9$/$J$k$H!"7QB3$NI=<($,$5$l$k$G(B + $B$7$g$&!#(B + + >> $B$r2!$7$F!"$b$&0lEY9T6g@Z$j$rA^F~$7$J$5$$!#(B + + Emacs$B$N$[$H$s$I$N%3%^%s%I$O!"7+$jJV$7$N2s?t$rM?$($k$3$H$,$G$-$^$9!#$3(B +$B$N$3$H$O!"J8;z$NA^F~$K$D$$$F$bEv$F$O$^$j$^$9!#(B + + >> C-u 8 * $B$HF~NO$7$F$_$J$5$$!#$I$&$J$j$^$7$?$+!#(B + + $BFs$D$N9T$N4V$K6uGr9T$r:n$j$?$$>l9g$K$O!"FsHVL\$N9T$N@hF,$K9T$-!"(BC-o $B$r(B +$BF~NO$7$^$9!#(B + + >> $BE,Ev$J9T$N@hF,$K9T$-!"$=$3$G(B C-o $B$rF~NO$7$F$_$J$5$$!#(B + + $B$3$l$G!"(BEmacs$B$G!"%F%-%9%H$rF~NO$7!"$^$?4V0c$$$r=$@5$9$k$b$C$H$b4pK\E*(B +$B$JJ}K!$r3X$s$@$3$H$K$J$j$^$9!#J8;z$HF1$8MM$K!"C18l$d9T$b:o=|$9$k$3$H$,$G$-(B +$B$^$9!#:o=|A`:n$K$D$$$FMWLs$9$k$H $B%+!<%=%k$ND>A0$NJ8;z$r:o=|(B + C-d $B%+!<%=%k$N$"$kJ8;z$r:o=|(B + + ESC $B%+!<%=%k$ND>A0$NC18l$r:o=|(B + ESC d $B%+!<%=%k0LCV0J9_$K$"$kC18l$r:o=|(B + + C-k $B%+!<%=%k0LCV$+$i9TKv$^$G$r:o=|(B + + $B2?$+$r:o=|$7$?8e$G!"$=$l$r85$KLa$7$?$/$J$k$3$H$,$"$j$^$9!#(BEmacs$B$O!"0l(B +$BJ8;z$h$j$bBg$-$$C10L$G:o=|$r9T$C$?;~$K$O!":o=|$7$?FbMF$rJ]B8$7$F$*$-$^$9!#(B +$B85$KLa$9$K$O!"(BC-y $B$r;H$$$^$9!#Cm0U$7$?$$$N$O!"(BC-y $B$r:o=|$r9T$C$?>l=j$@$1$G(B +$B$O$J$/!"$I$3$K$G$b=PMh$k$3$H$G$9!#(BC-y $B$O!"J]B8$5$l$?%F%-%9%H$r8=:_%+!<%=%k(B +$B$N$"$k>l=j$KA^F~$9$k$?$a$N%3%^%s%I$G$9$+$i!"$3$l$r;H$C$F%F%-%9%H$N0\F0$r9T(B +$B$&$3$H$,$G$-$^$9!#(B + + $B:o=|$r9T$&%3%^%s%I$K$O!"(B"Delete" $B%3%^%s%I$H!"(B"Kill" $B%3%^%s%I$H$,$"$j$^(B +$B$9!#(B"Kill" $B%3%^%s%I$G$O:o=|$5$l$?$b$N$OJ]B8$5$l$^$9$,!"(B"Delete" $B%3%^%s%I$G(B +$B$OJ]B8$5$l$^$;$s!#$?$@$7!"7+$jJV$72s?t$,M?$($i$l$k$H!"J]B8$5$l$^$9!#(B + + >> C-n $B$r#22s$[$I%?%$%W$7$F!"2hLL$NE,Ev$J>l=j$K0\F0$7$J$5$$!#$=$7$F!"(B + C-k $B$G!"$=$N9T$r:o=|$7$J$5$$!#(B + + $B0l2sL\$N(B C-k $B$G$=$N9T$NFbMF$,:o=|$5$l!"$b$&0lEY(B C-k $B$rF~NO$9$k$H!"$=$N(B +$B9T<+?H$,:o=|$5$l$^$9!#$b$7!"(BC-k $B$K7+$jJV$72s?t$r;XDj$7$?>l9g$K$O!"$=$N2s?t(B +$B$@$1$N9T$,!JFbMF$H9T<+?H$H$,F1;~$K!K:o=|$5$l$^$9!#(B + + $B:#:o=|$5$l$?%F%-%9%H$O!"J]B8$5$l$F$$$k$N$G!"$=$l$r> C-y $B$r;n$7$F$_$J$5$$!#(B + + C-k $B$r2?EY$bB3$1$F9T$&$H!":o=|$5$l$k%F%-%9%H$O!"$^$H$a$FJ]B8$5$l!"(BC-y +$B$G!"$=$NA4$F$,> C-k $B$r2?EY$b%?%$%W$7$F$_$J$5$$!#(B + + >> $B%F%-%9%H$r$N%F%-%9%H$r:o=|$9$k$H$I$&(B +$B$J$k$G$7$g$&$+!#(BC-y $B$O!"$b$C$H$b:G6a:o=|$5$l$?$b$N$r> $B9T$r:o=|$7!"%+!<%=%k$r0\F0$5$;!"JL$N9T$r:o=|$7$J$5$$!#(BC-y $B$r9T$&(B + $B$H!"#2HVL\$N9T$,F@$i$l$^$9!#(B + +$BC$7(B(UNDO) +============== + + $B$$$D$G$b!"%F%-%9%H$rJQ99$7$?$1$l$I$b!"$=$l$r$b$H$KLa$7$?$$$H$-$O(BC-x u +$B$GD>$j$^$9!#IaDL$O4V0c$($?%3%^%s%I$rL58z$K$9$kF/$-$r$7$^$9!#7+$jJV$7$F(BUNDO +$B$r9T$J$*$&$H$9$k;~$O!"2?EY$b$=$N%3%^%s%I$r9T$J$($P=PMh$k$h$&$K$J$C$F$$$^$9!#(B + + >> $B$3$N9T$r(BC-k$B$G>C$7$F2<$5$$!#$=$7$F!"(BC-x u$B$GLa$7$F2<$5$$!#(B + + C-_$B$O!"(BUNDO$B$r9T$J$&!"$b$&0l$D$N%3%^%s%I$G$9!#5!G=$O!"(BC-x u$B$HF1$8$G$9!#(B + + C-_$B$d(BC-x u$B$K(BUNDO$B$N2s?t$r!"M?$($k$3$H$,=PMh$^$9!#(B + + +$B%U%!%$%k(B +======== + + $B%F%-%9%H$X$NJQ99$r1J5WE*$K$9$k$?$a$K$O!"$=$l$r%U%!%$%k$KJ]B8$7$J$1$l$P(B +$B$J$j$^$;$s!#J]B8$5$l$J$$$H!"$[$I$3$7$?JQ99$O!"(BEmacs$B$r=*N;$9$k$HF1;~$K<:$o$l(B +$B$F$7$^$$$^$9!#(B + + $B$$$^8+$F$$$k%U%!%$%k$KBP$7$F!"$"$J$?$NJT=8$r9T$C$?$b$N$r=q$-9~$_$^$9!#(B +$B$$$^8+$F$$$k%U%!%$%k$H$O!"4JC1$K$$$($PJT=8$7$F$$$k%U%!%$%k<+BN$N$3$H$G$9!#(B + + $B$"$J$?$,%U%!%$%k$r%;!<%V!JJ]B8$9$k!K$9$k$^$G!":#$^$G$NJQ99$OJT=8$7$F$$(B +$B$k%U%!%$%k$K=q$-9~$^$l$k;v$O$"$j$^$;$s!#$=$l$O!"$"$J$?$,$=$N$h$&$K9T$$$?$/(B +$B$J$$$N$K!"ESCf$^$GJQ99$r2C$($?$b$N$,>!A0(B +$B$rJQ$($F%*%j%8%J%k$N%U%!%$%k$r;D$7$^$9!#(B + +$BHw9M(B: $B$^$?!"(BEmacs$B$OITB,$N;vBV$KBP$7!"0lDj$N%?%$%_%s%0$4$H$K<+F0E*(B + $B$KJT=8$7$F$$$k%U%!%$%k$NFbMF$rL>A0$rJQ$($?%U%!%$%k$K%;!<%V$7(B + $B$^$9!#$3$l$K$h$C$F!"K|0l$N>l9g$O9T$C$?$NJQ99$KBP$7:G>.8B$NHo(B + $B32$G:Q$`$h$&$K$J$C$F$$$^$9!#(B + + $B2hLL$N2<$NJ}$r8+$k$H!"$3$N$h$&$J46$8$G%b!<%I%i%$%s$,I=<($5$l$F$$$k$H;W(B +$B$$$^$9!#(B + + +($BNc(B) [--]J:--**-Mule: MULE.tut (Fundamental) ---55%-------------- + + + $B$3$N(BEmacs$B%A%e!<%H%j%"%k$N%3%T!<$O(BMULE.tut$B$H8F$P$l$F$$$^$9!#%U%!%$%k$r(B +$B%U%!%$%s%I!J%U%!%$%k$r8+$D$1$F%P%C%U%!$KFI$_9~$`$3$H!K$9$k$H!"(BMULE.tut$B$NIt(B +$BJ,$KI=<($5$l$^$9!#Nc$($P!"(Bnew-file$B$H$$$&L>A0$N%U%!%$%k$r%U%!%$%s%I$7$?$J$i(B +$B$P!"(B"Mule: new-file"$B$H$$$&%b!<%I%i%$%s$K$J$k$G$7$g$&!#(B + +$BCm0U!'(B $B%b!<%I%i%$%s$K$D$$$F$O8e$[$I@bL@$7$^$9!#>/$7$*BT$A$r!#(B + + $B%U%!%$%k$r%U%!%$%s%I$7$?$j!"%;!<%V$7$?$j$9$k%3%^%s%I$O!"$3$l$^$G$N$b$N(B +$B$H$O0c$$!"#2$D$NJ8;z$+$i$J$C$F$$$^$9!#(BC-x $B$KB3$$$FF~NO$9$kJ8;z$,!"%U%!%$%k(B +$B$KBP$7$F9T$&A`:n$rI=$7$^$9!#(B + + $B$b$&0l$D$3$l$^$G$N$b$N$H0c$&E@$O!"%U%!%$%s%I$N;~!"%U%!%$%kL>$r(BEmacs$B$K(B +$BLd$o$l$^$9!#$3$N$3$H$r!"Cl9g$O%U%!%$%kL>$G$9!#(B + + C-x C-f $B%U%!%$%k$r8+$D$1$k!J%U%!%$%s%I$9$k!K(B + + Emacs$B$O%U%!%$%kL>$rJ9$$$F$-$^$9!#$=$l$O!"2hLL$N2<$N9T$K8=$l$^$9!#%U%!(B +$B%$%kL>$r;XDj$7$F$$$kItJ,$O!"%_%K%P%C%U%!$H8F$P$l$k$b$N$G$9!#%_%K%P%C%U%!$O(B +$B$3$NMM$J;H$o$lJ}$r$7$^$9!#%U%!%$%kL>$KB3$$$F!"%j%?!<%s%-!<$r2!$9$H!"%_%K%P(B +$B%C%U%!$KI=<($5$l$F$$$?FbMF$O$b$&I,MW$G$O$J$/$J$k$N$G>C$($F$7$^$$$^$9!#(B + + >> C-x C-f$B$H%?%$%W$7$?8e$K(BC-g$B$H%?%$%W$7$F2<$5$$!#%_%K%P%C%U%!$NFbMF(B + $B$rC$7!"$^$?!"(BC-x C-f$B%3%^%s%I$bC$7$^$9!#$H8@$&Lu$G!"2?$b(B + $B%U%!%$%k$r8+$D$1$k$h$&$J$3$H$O$7$^$;$s!#(B + + $B:#EY$O%U%!%$%k$r%;!<%V$7$F$_$^$7$g$&!#:#$^$G$NJQ99$rJ]B8$9$k$?$a$K$OA0$r$D$1$i$l$F;D$5$l$F$$$k$N$GFbMF$O<:$o$l$^$;$s!#$=(B +$B$N?7$7$$L>A0$O%*%j%8%J%k$N%U%!%$%k$NL>A0$K(B'~'$B$r$D$1$?$b$N$G$9!#(B + + $B%;!<%V$,=*$o$k$H!"(BEmacs$B$O%;!<%V$7$?%U%!%$%k$NL>A0$rI=<($7$^$9!#(B + + >> C-x C-s$B$H%?%$%W$7$F%A%e!<%H%j%"%k$N%3%T!<$r%;!<%V$7$F2<$5$$!#$=$N(B + $B;~!"2hLL$N2<$NJ}$K(B"Wrote ...../MULE.tut"$B$HI=<($5$l$^$9!#(B + + $B?7$7$$%U%!%$%k$r:n$k;~!"$"$?$+$b0JA0$+$i$"$C$?%U%!%$%k$r%U%!%$%s%I$9$k(B +$B$h$&$J%U%j$r$7$^$9!#$=$&$7$F!"$=$N%U%!%$%s%I$7$?%U%!%$%k$K%?%$%W$7$F$$$-$^(B +$B$9!#(B + + $B%U%!%$%k$r%;!<%V$7$h$&$H$7$?;~$K=i$a$F!"(BEmacs$B$O:#$^$GJT=8$7$F$$$?FbMF(B +$B$r%U%!%$%k$NCf$K=q$-9~$_$^$9!#(B + + +$B%P%C%U%!(B +======== + + $B$b$7!"#2HVL\$N%U%!%$%k$r(B C-x C-f $B$G> C-x C-b $B$H%?%$%W$7$J$5$$!#$=$l$>$l$N%P%C%U%!$,$I$N$h$&$KL>A0$r;}(B + $B$C$F$$$k$+!"$=$7$F!"$I$N$h$&$J%U%!%$%kL>$r$D$1$F$$$k$N$+4Q;!$7$J(B + $B$5$$!#(B + + $B%P%C%U%!$K$O%U%!%$%k$H0lCW$J$$$b$N$b$"$j$^$9!#$?$H$($P!"(B +"*Buffer List*" $B$H$$$&%U%!%$%k$O$"$j$^$;$s!#$3$l$O(B C-x C-b $B$K$h$C$F:n$i$l(B +$B$?%P%C%U%!%j%9%H$KBP$7$F$N%P%C%U%!$G$9!#(B + + $B$"$J$?$,8+$F$$$k(BEmacs$B%&%#%s%I%&Fb$K$"$k!"$I$s$J%F%-%9%H$G$b!"$$$:$l$+(B +$B$N%P%C%U%!Fb$K$"$j$^$9!#(B + + >> $B%P%C%U%!%j%9%H$r>C$9$?$a(B C-x 1 $B$H%?%$%W$7$J$5$$!#(B + + $B$b$7!"$"$k%U%!%$%k$N%F%-%9%H$KJQ99$r9T$J$C$F$+$i!"B>$N%U%!%$%k$rA0$K$h$k3HD%!#B3$1$F%3%^%s%I$NL>A0$rF~NO$7$^$9!#(B + + $B$3$l$i$O0lHL$K!"JXMx$@$1$l$I$b!"$3$l$^$G8+$F$-$?$b$N$[$IIQHK$K$OMQ$$$i(B +$B$l$J$$%3%^%s%I$N$?$a$N$b$N$G$9!#(BC-x C-f $B!J%U%!%$%s%I!K$d(B C-x C-s$B!J%;!<%V!K(B +$B$O$3$NCg4V$G$9!#B>$K!"(BC-x C-c$B!J%(%G%#%?$N=*N;!K$b$=$&$G$9!#(B + + C-z$B$O(BEmacs$B$rH4$1$k$N$KNI$/;H$o$l$kJ}K!$G$9!#(BEmacs$B$r=*N;$9$k$3$H$J$/!"(B +$B0lC6!"(Bcsh$B$N%l%Y%k$KLa$k$K$O0lHVNI$$J}K!$H8@$($k$G$7$g$&!#(BC-z$B$r9T$J$o$l$F$b(B +Emacs$B$O%9%H%C%W$7$F$$$k$@$1$G!"FbMF$,GK2u$5$l$k$H$$$&$3$H$O$"$j$^$;$s!#(B + +$BCm0U(B: $B$?$@$7(BX-window$B$G9T$J$C$F$$$k>l9g!"$b$7$/$O;HMQ$7$F$$$k%7%'%k(B + $B$,(Bsh$B$N;~$O!"$3$N8B$j$G$O$"$j$^$;$s!#(B + + + C-x $B%3%^%s%I$O!"$?$/$5$s$"$j$^$9!#$9$G$K3X$s$@$b$N$O0J2<$N$b$N$G$9!#(B + + C-x C-f $B%U%!%$%k$NJT=8!J(BFind$B!K(B + C-x C-s $B%U%!%$%k$NJ]B8!J(BSave$B!K(B + C-x C-b $B%P%C%U%!%j%9%H$NI=<((B + C-x C-c $B%(%G%#%?$r=*N;$9$k!#%U%!%$%k$NJ]B8$O!"<+F0E*$K$O9T$o$l$^$;(B + $B$s!#$7$+$7!"$b$7%U%!%$%k$,JQ99$5$l$F$$$l$P!"%U%!%$%k$NJ]B8(B + $B$r$9$k$N$+$I$&$+$rJ9$$$F$-$^$9!#J]B8$7$F=*N;$9$kIaDL$NJ}K!(B + $B$O!"(BC-x C-s C-x C-c $B$H$9$k$3$H$G$9!#(B + + $BL>A0$K$h$k3HD%%3%^%s%I$K$O!"$"$^$j;H$o$l$J$$$b$N$d!"FCDj$N%b!<%I$G$7$+(B +$B;H$o$J$$$b$N$J$I$,$"$j$^$9!#Nc$H$7$F!"(B"command-apropos" $B$r$H$j$"$2$^$9!#$3(B +$B$N%3%^%s%I$O%-!<%o!<%I$rF~NO$5$;!"$=$l$K%^%C%A$9$kA4$F$N%3%^%s%I$NL>A0$rI=(B +$B<($7$^$9!#(BESC x $B$H%?%$%W$9$k$H!"%9%/%j!<%s$N2<$K(B "M-x" $B$,I=<($5$l$^$9!#$3$l(B +$B$KBP$7$F!"A0!J:#$N>l9g!"(B"command-apropos"$B!K$rF~NO$7$^$9!#(B +"command-a" $B$^$GF~NO$7$?8e%9%Z!<%9$rF~$l$l$P!"8e$NItJ,$O<+F0E*$KJd$o$l$^$9!#(B +$B$3$N8e!"%-!<%o!<%I$rJ9$+$l$^$9$+$i!"CN$j$?$$J8;zNs$r%?%$%W$7$^$9!#$J$*!"%-!<(B +$B%o!<%I$rF~$l$J$$$H!"A4$F$N%3%^%s%I$,I=<($5$l$^$9!#(B + + >> ESC x $B$r%?%$%W$7!"B3$1$F!"(B"command-apropos" $B$"$k$$$O(B + "command-a" $B$H%?%$%W$7$^$9!#" + $B$H%?%$%W$7$^$9!#(B + + $B8=$l$?!V%&%#%s%I%&!W$r>C$9$K$O!"(BC-x 1 $B$H%?%$%W$7$^$9!#(B + +$B%b!<%I%i%$%s(B +============ + + $B$b$7$f$C$/$j$H%3%^%s%I$rBG$C$?$J$i$P!"2hLL$N2l=j$KBG$C$?$b$N$,I=<($5$l$^$9!#%(%3!<%(%j%"$O2hLL$N(B1$B$P$s2<$N9T$G$9!#$=$N(B +$B$9$0>e$N9T$O!"%b!<%I%i%$%s$H8F$P$l$F$$$^$9!#%b!<%I%i%$%s$O$3$s$JIw$KI=<($5(B +$B$l$F$$$k$G$7$g$&!#(B + + [--]J:--**-Mule: MULE.tut (Fundamental) ---NN%-------------- + + +$BCm0U(B: NN%$B$N(BNN$B$O?t;z$,F~$C$F$$$^$9!#$"$J$?$,;H$C$F$$$k(BEmacs$B$N%b!<(B + $B%I%i%$%s$H0c$&$+$bCN$l$J$$$1$I!"92$F$J$$$h$&$K!#Nc$($P!";~4V(B + $B$d(Buptime$B$,I=<($5$l$F$$$k$N$O!"(Bdisplay-time$B$H$$$&5!G=$,F0$$$F(B + $B$$$k$+$i$G$9!#(B + + $B$3$N9T$K$h$C$FB?$/$NM-MQ$J>pJs$,F@$i$l$^$9!#(B + + + $B:#!"$"$J$?$,8+$F$$$k%U%!%$%kL>$rI=<($7$F$$$^$9!#(BNN%$B$O8=:_%9%/%j!<%s>e(B +$B$K%U%!%$%k$N0lHV>e$+$i2?%Q!<%;%s%HL\$,I=<($5$l$F$$$k$+$r<($7$F$$$^$9!#%U%!(B +$B%$%k$N0lHV:G=i$rI=<($7$F$$$k$J$i$P!"(B--Top--$B$HI=<($5$l$F$^$9!#%U%!%$%k$N0lHV(B +$B:G8e$rI=<($7$F$$$k$J$i$P!"(B--Bot--$B$HI=<($5$l$^$9!#2hLL$NCf$K%U%!%$%k$NA4$F$,(B +$BI=<($5$l$F$$$k$J$i$P!"(B--All--$B$HI=<($5$l$^$9!#(B + + $B%b!<%I%i%$%s$N>.3g8L$NCf$O!":#$I$s$J%b!<%I$KF~$C$F$$$k$+$r<($7$F$$$^$9!#(B +$B8=:_$O!"%G%U%)%k%H$N(BFundamental$B$KF~$C$F$$$^$9!#$3$l$b%a%8%c!<%b!<%I$N0lNc$G(B +$B$9!#(B + + Emacs$B$O(BLisp mode$B$d(BText mode$B$N$h$&$J$3$H$J$k%W%m%0%i%`8@8l$d%F%-%9%H$K(B +$BBP$7$F%(%G%#%C%H$r9T$&$?$a$N4v$D$+$N%a%8%c!<%b!<%I$r;}$C$F$$$^$9!#$I$s$J;~(B +$B$G$bI,$:$$$:$l$+$N%a%8%c!<%b!<%I$N>uBV$K$J$C$F$$$^$9!#(B + + $B$=$l$>$l$N%a%8%c!<%b!<%I$O4v$D$+$N%3%^%s%I$rA4$/0c$&?6$kIq$$$K$7$F$7$^(B +$B$$$^$9!#Nc$r>e$2$F$_$^$7$g$&!#%W%m%0%i%`$NCf$K%3%a%s%H$r:n$k%3%^%s%I$,$"$j(B +$B$^$9!#%3%a%s%H$r$I$NMM$J7A<0$K$9$k$+$O!"3F%W%m%0%i%`8@8l$K$h$C$F0c$$$^$9$,!"(B +$B$=$l$>$l$N%a%8%c!<%b!<%I$O!"$-$A$s$HF~$l$F$/$l$^$9!#(B + + $B$=$l$>$l$N%a%8%c!<%b!<%I$KF~$k$?$a$N%3%^%s%I$O%b!<%IL>$N3HD%$5$l$?$b$N(B +$B$K$J$C$F$$$^$9!#Nc$($P!"(BM-x fundamental-mode$B$O(BFundamental$B$KF~$k$?$a$N$b$N$G(B +$B$9!#(B + + $B$b$7!"1Q8l$r%(%G%#%C%H$9$k$J$i$P!"(BText mode$B$KF~$j$^$9!#(B + + >> M-x text-mode $B$H%?%$%W$7$J$5$$!#(B + + $B8=:_$N%a%8%c!<%b!<%I$K$D$$$F$N%I%-%e%a%s%H$r8+$?$$;~$O!"(BC-h m$B$H%?%$%W(B +$B$7$^$9!#(B + + >> C-h m $B$r;H$C$F(BText mode$B$H(BFundamental mode$B$N0c$$$rD4$Y$J$5$$!#(B + + >> C-x 1$B$G%I%-%e%a%s%H$r2hLL$+$i>C$7$J$5$$!#(B + + $B:8C<$N(B '[--]' $B$O8=:_$N%-!\$7$$@bL@$O(B +$B!V$?$^$4!W$N%^%K%e%"%k$rD4$Y$F2<$5$$!#(B + + $B$=$N$9$01&$K$O%3!<%IBN7O(B (coding-system) $B$K4X$9$k%U%i%0$N>uBV$,I=(B +$B<($5$l$F$$$^$9!#(BMule $B$O!"%U%!%$%kF~=PNO!"F~NO!"2hLL=PNO$K$D$$$F!"$=$l$>$lFH(B +$BN)$K%3!<%IBN7O$r;XDj$5$;$k$3$H$,=PMh$^$9$,!"DL>o$O%U%!%$%kMQ$N%3!<%IBN7O$N(B +$B%K!<%b%K%C%/$N$_I=<($7$F$$$^$9!#(B + + >> $B%b!<%I%i%$%s>e$K(B"J:","S:",$B$b$7$/$O(B "E:"$B$,I=<($5$l$F$$$k$+$I$&$+3N(B + $BG'$7$J$5$$!#(B + + $B:G=i$N0lJ8;z$,%3!<%IBN7O$N%K!<%b%K%C%/!"> C-x C-k t$B$r(B2$BEY9T$$$J$5$$!#(B + + $BF~NO%b!<%I$,(BJIS$B%3!<%I$N@_Dj$H$J$C$F$$$k;~!"$b$7$"$J$?$N;H$C$F$$$kC$B$b(BM-<$BJ8;z(B>$B$bF1$8F/$-$r$7$^$9!#:#$^$G$N@bL@$G(BESC +<$BJ8;z(B>$B$H9T$J$C$F$$$?$H$3$m$,!"(BM-<$BJ8;z(B>$B$H$J$j$^$9!#Cm0U$7$J$1$l$P$J$i$J$$$N(B +$B$O!"%7%U%H(BJIS$B$d(BEUC$B%3!<%I$N;~$O;HMQ$G$-$^$;$s!#(B + + $B%3!<%IBN7O$N$N@Z$jBX$($O!"3F!9$N%P%C%U%!$KBP$7$F$N$_M-8z$G$9!#$=$l$>$l(B +$B$N!"%3!<%IBN7O;XDj$K$D$$$F$O!"(BC-h a coding-system $B$G8+$k$3$H(B +$B$,=PMh$^$9!#(B + + >> C-h a coding-system $B$G=P$F$/$k%I%-%e%a%s%HCf$N!"(B + set-display-coding-system, set-file-coding-system, + set-process-coding-system $B$N@bL@$rFI$_$J$5$$!#(B + +$B8!:w(B +===== + + $BJ8;zNs$r!"%U%!%$%kFb$G!"A0J}Kt$O8eJ}$K!"C5$9;v$,$G$-$^$9!#8!:w$r;O$a$k(B +$B%3%^%s%I$O!"%+!<%=%k0LCV0J9_$r8!:w$9$k$J$i$P(B C-s$B!"%+!<%=%k0LCV0JA0$J$i$P(B +C-r $B$G$9!#(BC-s $B$r%?%$%W$9$k$H!"%(%3!<%(%j%"$K(B "I-search:"$B$H$$$&J8;zNs$,%W%m(B +$B%s%W%H$H$7$FI=<($5$l$^$9!#(BESC$B$r2!$9$H!"=*N;$G$-$^$9!#(B + + + >> C-s$B$G8!:w$,;O$^$j$^$9!#$=$l$+$i!"$f$C$/$j$H#1J8;z$:$D(B"cursor"$B$H$$(B + $B$&C18l$rF~NO$7$^$9!##1J8;zF~NO$9$k$4$H$K!"%+!<%=%k$O!"$I$s$JF0$-(B + $B$r$7$^$9$+(B? + + >> $B$b$EY(B C-s $B$r%?%$%W$9$k$H!"> $B$r#42sF~NO$7$F!"%+!<%=%k$NF0$-$r8+$J$5$$!#(B + + >> ESC$B$r2!$7$F!"=*N;$7$^$9!#(B + + $BC5$7$?$$J8;zNs$r%?%$%WCf$G$b!"%?%$%W$7$?J8;zItJ,$@$1$G!"8!:w$r;O$a$^$9!#(B +$B$B$rF~NO$9$k$H!"8!:wJ8;zNs$N#1HV8e$m$NJ8;z$,>C$($^$9!#(B +$B$=$7$F!"%+!<%=%k$O!"A02s$N0LCV$KLa$j$^$9!#$?$H$($P!"(B"cu"$B$H%?%$%W$7$F!":G=i(B +$B$N(B"cu"$B$N0LCV$K%+!<%=%k$,F0$$$?$H$7$^$9!#$3$3$G(B$B$rF~NO$9$k$H!"%5!<%A(B +$B%i%$%s$N(B'u'$B$,>C$(!"%+!<%=%k$O!"(B'u'$B$r%?%$%W$9$kA0$K!"%+!<%=%k$,$"$C$?(B'c'$B$N0L(B +$BCV$K!"0\F0$7$^$9!#(B + + $B8!:wuBV$K(B +$BF~$k$3$H$,$"$j$^$9!#%a%8%c!<%b!<%I$N>.3g8L(B'()'$B$N2s$j$rCf3g8L(B'[]'$B$G0O$s$@$b(B +$B$N$,%b!<%I%i%$%s>e$KI=<($5$l$^$9!#Nc$($P!"(B(Fundamental)$B$HI=<($5$l$kBe$o$j$K(B +[(Fundamental)]$B$N$h$&$K$J$j$^$9!#(B + +$BCm0U(B: $B$3$3$G$O%j%+!<%7%V(B $B%(%G%#%F%#%s%0(B $B%l%Y%k<+BN$K$D$$$F$O@bL@$7(B + $B$^$;$s!#(B + + $B%j%+!<%7%V(B $B%(%G%#%F%#%s%0(B $B%l%Y%k$+$iH4$1$G$k$?$a$K$O!"(BM-x top-level +$B$H%?%$%W$7$^$9!#(B + + >> $B;n$7$F$_$F2<$5$$!#%9%/%j!<%s$NDl$K(B"Back to top level"$B$HI=<($5$l$^(B + $B$9!#(B + + $BK\Ev$O!"$3$N;n$_$,9T$o$l$?;~$O!"$9$G$K%H%C%W%l%Y%k$K$$$?$N$G$9!#(BM-x +top-level$B$O!"2?$b1F6A$rM?$($F$$$^$;$s!#(B + + $B%j%+!<%7%V(B $B%(%G%#%F%#%s%0(B $B%l%Y%k$+$iH4$1=P$k$N$KBP$7$F$O(BC-g$B$O8z$-$^$;(B +$B$s!#(B + + +$B%X%k%W(B +====== + + Emacs$B$K$O!"$?$/$5$s$NLr$KN)$D5!G=$,$"$j!"$3$3$G!"$9$Y$F$r@bL@$9$k$3$H(B +$B$O!"IT2DG=$G$9!#$7$+$7!"$^$@CN$i$J$$B?$/$N5!G=$r3X$V$?$a$K$O!"(B$B$H8F$P(B +$B$l$k(B C-h $B$r%?%$%W$9$k$3$H$G!"$?$/$5$s$N>pJs$rC$9(B +$B$3$H$,$G$-$^$9!#(B + + $B:G$b4pK\E*$J$b$N$O!"(BC-h c $B$G$9!#$3$l$KB3$$$F%-!<$rF~NO$9$k$H!"$=$N%3%^(B +$B%s%I$K$D$$$F$NC;$$@bL@$rI=<($7$^$9!#(B + + >> C-h c C-p $B$H%?%$%W$7$F$_$J$5$$!#(B"C-p runs the command previous- + line"$B$N$h$&$J%a%C%;!<%8$,I=<($5$l$k$O$:$G$9!#(B + + $B8+$?$3$H$O$"$k$,!"3P$($F$O$$$J$$%3%^%s%I$b;W$$=P$;$k$N$G$9!#(BC-x C-s $B$N(B +$B$h$&$JJ#?t$G#1$D$N%3%^%s%I$b(BC-h c $B$N8e$m$KB3$1$i$l$^$9!#(B + + $B$b$C$H>\$7$/CN$j$?$+$C$?$i!"(Bc $B$NBe$o$j$K(B k $B$r;XDj$7$^$9!#(B + + >> C-h k C-p $B$H%?%$%W$7$F$_$J$5$$!#(B + + Emacs$B$N%&%#%s%I%&$K!"%3%^%s%I$NL>A0$H5!G=$,I=<($5$l$^$9!#FI$_=*$($?$i!"(B +C-x 1 $B$H%?%$%W$9$k$H!"H4$1$i$l$^$9!#(B + + $BB>$K$bLr$KN)$D%*%W%7%g%s$,$"$j$^$9!#(B + + C-h f $B%U%!%s%/%7%g%sL>$rF~NO$9$k$H!"%U%!%s%/%7%g%s$rI=<($7$^$9!#(B + + >> C-h f previous-line $B$r%?%$%W$7!"(B $B$r2!$7$J$5$$!#(BC-p $B%3%^%s(B + $B%I$rpJs$rI=<($7$^$9!#(B + + C-h a $B%-!<%o!<%I$rF~NO$9$k$H!"L>A0$K$=$N%-!<%o!<%I$r4^$`!"A4$F$N%3(B + $B%^%s%I$rI=<($7$^$9!#$3$l$i$N%3%^%s%I$O$9$Y$F(BESC x $B$G> C-h a file $B$H%?%$%W$7!"(B$B$r2!$7$J$5$$!#L>A0$K(B"file"$B$H$$$&J8(B + $B;z$r;}$DA4$F$N%3%^%s%I$rI=<($7$^$9!#$^$?!"(Bfind-file $B$d(B write-file + $B$H$$$&L>$N(B C-x C-f $B$d(B C-x C-w $B$N$h$&$J%3%^%s%I$bI=<($5$l$^$9!#(B + +$B$*$o$j$K(B +======== + +$BK:$l$:$K!'(B $B=*N;$9$k$K$O!"(BC-x C-c $B$H$7$^$9!#(B + + + $B$3$NF~LgJT$O!"$^$C$?$/$N=i?4o$KB?$/$N$3$H$,$G$-$k>l9g$K$OFC$K$=$&$G$7$g(B +$B$&!#$=$7$F!"(BEMACS $B$G$O!"O$O(BGMW + +Wnn + Nemacs$B$r;H$C$F=q$-$^$7$?!#$=$N$h$&$JAG@2$i$7$$%W%m%0%i%`$r:n$C$?J}!9(B +$B$X46M;R$5$s!"$I$&$b$"$j$,$H$&!#(B + + + + + +$B8mLu!"13!"$=$NB>!"$NJ8@U$O!"0J2<$N>" $B$+$i;O$^$k9T$O!"$=$N;~2?$r$9$Y$-$+$r;X<($7$F$$$^$9!#(B - - - Mule $B$N%3%^%s%I$rF~NO$9$k$H$-$K$O!"0lHLE*$K%3%s%H%m!<%k!&%-! $B%3%s%H%m!<%k!&%-!<$r2!$7$?$^$^!"(B<$BJ8;z(B>$B%-!<$r2!$7$^$9!#Nc$($P!"(B - C-f $B$O!"%3%s%H%m!<%k!&%-!<$r2!$7$J$,$i(B f $B$N%-!<$r2!$9$3$H$r(B - $B0UL#$7$^$9!#(B -<> - >> $B$=$l$G$O!"(BC-v$B!J(BView Next Screen; $B $B%(%9%1!<%W!&%-!<$r2!$7$F$+$iN%$7!"$=$l$+$i(B<$BJ8;z(B>$B%-!<$r2!$7$^(B - $B$9!#(B - -$BCm0U!'(B <$BJ8;z(B>$B$O!"BgJ8;z$G$b>.J8;z$G$b%3%^%s%I$H$7$F$OF1$80UL#$K$J$j(B - $B$^$9!#%a%?%-!<$,;H$($k$J$i$P(B ESC <$BJ8;z(B> $B$NBe$o$j$K(B M-<$BJ8;z(B> - ($B%a%?%-!<$r2!$7$?$^$^(B<$BJ8;z(B>$B%-!<$r2!$9(B) $B$,;H$($^$9!#(B - -$B=EMW$G$9!'(B Emacs$B$r=*N;$5$;$?$$;~$O!"(BC-x C-c $B$r%?%$%W$7$^$9!#(BEmacs$B$r(Bcsh - $B$+$i5/F0$7$F$$$k>l9g!"%5%9%Z%s%I$9$k!J0l;~E*$K;_$a$k(B)$B$3$H$,(B - $B=PMh$^$9!#(BEmacs$B$r%5%9%Z%s%I$9$k$K$O!"(BC-z$B$r%?%$%W$7$^$9!#(B - - - $B$5$F!"$3$l$+$i$O!"0l2hLLJ,FI$_=*$($?$i!"(BC-v $B$rF~NO$7$F9T$C$F2<$5$$!#(B - - $BA0$N2hLL$H> ESC v $B$H(B C-v $B$r;H$C$F!"A08e$K0\F0$9$k$3$H$r2?2s$+;n$7$F$_$J$5$$!#(B - -$BMWLs(B -==== - $B%U%!%$%k$r2hLLKh$K8+$F9T$/$K$O!"$9!#$3$N$H$-!"85%+!<%=%k$N$"$C$?9T$,(B - $B2hLL$NCf1{$K$/$k$h$&$K$9$k(B - - >> $B:#%+!<%=%k$,$I$3$K$"$k$+!"$=$N6a$/$K$I$s$J%F%-%9%H$,=q$+$l$F$$$k(B - $B$+$r3P$($J$5$$!#(BC-l $B$r%?%$%W$7!"%+!<%=%k$,$I$3$K0\F0$7$?$+!"$=$N(B - $B6a$/$N%F%-%9%H$O$I$&$J$C$?$+$rD4$Y$F$_$J$5$$!#(B - -$B4pK\E*$J%+!<%=%k$N@)8f(B -====================== - - $B2hLLKh$N0\F0$O$G$-$k$h$&$K$J$j$^$7$?!#:#EY$O!"2hLL$NCf$G!"FCDj$N>l=j$K(B -$B0\F0$9$k$?$a$NJ}K!$r21$($^$7$g$&!#$3$l$K$O$$$/$D$+$N$d$jJ}$,$"$j$^$9!#0l$D(B -$B$NJ}K!$O!"A0(B(previous)$B$l!"(BC-p, C-n, C-f,C-b $B$K3d$jEv$F$i$l$F(B -$B$*$j!"8=:_$N>l=j$+$i?7$7$$>l=j$K%+!<%=%k$r0\F0$5$;$^$9!#?^$G=q$1$P!"(B - - - $BA0$N9T!$(BC-p - : - : - $B8e$NJ8;z!$(BC-b .... $B8=:_$N%+!<%=%k0LCV(B .... $B@h$NJ8;z!$(BC-f - : - : - $B$l!"(BPrevious, Next, Backward, Forward $B$NF,J8;z$K$J$C$F(B -$B$$$k$N$G!"21$($d$9$$$G$7$g$&!#$3$l$i$O!"4pK\E*$J%+!<%=%k0\F0%3%^%s%I$G$"$j!"(B -$B$$$D$G$b;H$&$b$N$G$9!#(B - - >> C-n $B$r2?2s$+%?%$%W$7!"!J:#!"$"$J$?$,FI$s$G$$$k!K$3$N9T$^$G%+!<%=(B - $B%k$r0\F0$5$;$J$5$$!#(B - - >> C-f $B$r;H$C$F9T$NCf$[$I$K0\F0$7!"(BC-p $B$G2?9T$+>e$K0\F0$7$F$_$J$5(B - $B$$!#%+!<%=%k$N0LCV$NJQ2=$KCm0U$7$J$5$$!#(B - - >> $B9T$N@hF,$G(B C-b $B$r%?%$%W$7$F$_$J$5$$!#%+!<%=%k$O$I$3$K0\F0$7$^$9$+(B - $B!)$5$i$K$b$&>/$7(B C-b $B$r%?%$%W$7!":#EY$O(B C-f $B$G9TKv$NJ}$KLa$j$J$5(B - $B$$!#%+!<%=%k$,9TKv$r1[$($k$H$I$&$J$j$^$9$+!)(B - - - $B2hLL$N@hF,$dKvHx$r1[$($F%+!<%=%k$r0\F0$5$;$h$&$H$9$k$H!"$=$NJ}8~$K$"$k(B -$B%F%-%9%H$,0\F0$7$FMh$F!"%+!<%=%k$O>o$K2hLLFb$K$"$k$h$&$K$5$l$^$9!#(B - - >> C-n $B$r;H$C$F!"%+!<%=%k$r2hLL$N2> ESC f $B$d(B ESC b $B$r2?2s$+%?%$%W$7$F$_$J$5$$!#(BC-f $B$d(B C-b $B$HJ;MQ$7$F(B - $B$_$J$5$$!#(B - - C-f $B$d(B C-b $B$KBP$9$k!"(BESC f $B$d(B ESC b $B$NN`;w@-$KCmL\$7$^$7$g$&!#B?$/$N(B -$B>l9g!"(BESC <$BJ8;z(B>$B$OJ8=q4X78$N=hM}$K;H$o$l!"0lJ}(BC-<$BJ8;z(B>$B$O$=$l$h$j$b$b$C$H4p(B -$BK\E*$JBP>]!JJ8;z$H$+9T$H$+!K$KBP$9$kA`:n$K;H$o$l$^$9!#(B - - C-a $B$H(B C-e $B$bCN$C$F$$$FJXMx$J%3%^%s%I$G$9!#(BC-a $B$O%+!<%=%k$r9T$N@hF,$K(B -$B0\F0$5$;!"(BC-e $B$O9T$NKvHx$K0\F0$5$;$^$9!#(B - - - >> C-a $B$r#22s!"$=$l$+$i(B C-e $B$r#22sF~NO$7$F$_$J$5$$!#$3$l$i$N%3%^%s%I(B - $B$r#22s0J>e7+JV$7$F$b!"%+!<%=%k$O$=$l0J>e0\F0$7$J$$$3$H$KCm0U!#(B - - $B$"$HFs$D!"4JC1$J%+!<%=%k0\F0%3%^%s%I$,$"$j$^$9!#%U%!%$%k$N@hF,$K0\F0$9(B -$B$k(B ESC < $B$H!"%U%!%$%k$NKvHx$K0\F0$9$k(B ESC > $B$G$9!#(B - - $B%F%-%9%HCf$G%+!<%=%k$NB8:_$9$k0LCV$r!V%]%$%s%H!W$H8F$S$^$9!#8@$$$+$($l(B -$B$P!"%+!<%=%k$O!"%F%-%9%H$N$I$3$K%]%$%s%H$,$"$k$+$r2hLL>e$G<($7$F$$$k$N$G$9!#(B - - $B0J2<$KC1=c$J0\F0A`:n$K$D$$$FMWLs$7$^$9!#$3$N$J$+$K$O!"C18l$d9TC10L$G$N(B -$B0\F0%3%^%s%I$b4^$^$l$F$$$^$9!#(B - - C-f $B0lJ8;z@h$K?J$`(B - C-b $B0lJ8;z8e$KLa$k(B - - ESC f $B0lC18l@h$K?J$`(B - ESC b $B0lC18l8e$KLa$k(B - - C-n $B $B%U%!%$%k$N:G8e$K0\F0(B - - >> $B3F!9$N%3%^%s%I$r;n$7$F$_$J$5$$!#$3$l$i$N%3%^%s%I$O!":G$b$7$P$7$P(B - $B;H$o$l$k$b$N$G$9!#:G8e$NFs$D$G$O!"$3$N>l=j$H$ON%$l$?$H$3$m$K0\F0(B - $B$9$k$N$G!"(B C-v $B$d(B ESC v $B$r;H$C$F$3$3$KLa$C$FMh$k$h$&$K$7$J$5$$!#(B - - Emacs$B$NB>$N%3%^%s%I$HF1MM$K!"$3$l$i$N%3%^%s%I$K$O!"7+$jJV$7$N2s?t$r;X(B -$BDj$9$k0z?t(B $B$rM?$($k$3$H$,$G$-$^$9!#$=$N$?$a$K$O!"%3%^%s%I$rF~NO$9$kA0$K!"(B -C-u$B$KB3$$$F7+$jJV$92s?t$rF~NO$7$^$9!#(B - - $BNc$($P!"(BC-u 8 C-f $B$H$9$k$H!"#8J8;zJ,@h$K0\F0$7$^$9!#(B - - >> C-n $B$"$k$$$O(B C-p $B$KE,Ev$J0z?t$r;XDj$7$F!"0l2s$N0\F0$G$J$k$Y$/$3(B - $B$N9T$N6a$/$KMh$k$h$&$K$7$F$_$J$5$$!#(B - - C-v $B$d(B ESC v $B$K$D$$$F$O>/$70c$$$^$9!#$3$N>l9g!";XDj$5$l$??t$N9T$@$12h(B -$BLL$r0\F0$9$k$3$H$K$J$j$^$9!#(B - - >> C-u 3 C-v $B$HF~NO$7$F$_$J$5$$!#(B - - $B85$KLa$k$K$O!"(BC-u 3 ESC v $B$r;H$($P$h$$$N$G$9!#(B - -$BCf;_%3%^%s%I(B -============ - - C-g $B$H$$$&%3%^%s%I$G!"F~NO$rI,MW$H$9$k$h$&$J%3%^%s%I$rCf;_$9$k$3$H$,(B -$B$G$-$^$9!#Nc$($P!"0z?t$rF~NO$7$F$$$kESCf$d!"#2$D0J>e$N%-!> C-u 100 $B$r%?%$%W$7$F0z?t$r#1#0#0$K@_Dj$7!"(BC-g $B$r%?%$%W$7$J$5$$!#(B - $B$=$N$"$H$G(B C-f $B$r%?%$%W$7$F$_$J$5$$!#2?J8;z0\F0$7$^$7$?$+!)$b$7(B - $B4V0c$C$F(B ESC $B$rF~NO$7$F$7$^$C$?;~$b!"(BC-g $B$rF~NO$9$l$PC$;$^(B - $B$9!#(B - -$B%(%i!<(B -====== - - $B;~$K$O!"(BEmacs$B$G5v$5$l$F$$$J$$A`:n$r$7$F$7$^$&$3$H$,$"$j$^$9!#Nc$($P!"(B -$B%3%^%s%I$NDj5A$5$l$F$$$J$$%3%s%H%m!<%k!&%-!<$rF~NO$7$F$7$^$C$?;~$K$O!"(BEmacs -$B$O%Y%k$rLD$i$7!"$5$i$K!"2hLL$N0lHV2<$K!"2?$,0-$+$C$?$+$rI=<($7$^$9!#(B - - Emacs$B$N%P!<%8%g%s$K$h$C$F$O!"$3$NF~LgJT$K=q$+$l$F$$$k$3$H$rl9g$,$"$jF@$^$9!#$=$NMM$J>l9g$K$O!"%(%i!<%a%C%;!<%8$,I=<($5$l$^$9$+$i!"(B -$B2?$+%+!<%=%k0\F0%-!<$r2!$7$F!"$=$N$l$KBP$7$F%F%-%9%H$r(B -$BI=<($9$k$3$H$,$G$-$^$9!#%X%k%W$d!"4v$D$+$N%3%^%s%I$+$i$N=PNO$rI=<($9$k$?$a(B -$B$K8=$l$?M>J,$J%&%#%s%I%&$r>C$9$?$a$K!"$N%&%#%s%I%&$r>C$7$F!"%+!<%=%k$N$"$k%&%#%s%I%&$r!"2hLLA4BN(B -$B$K9-$2$^$9!#(B - - >> $B%+!<%=%k$r$3$N9T$K;}$C$F$-$F!"(BC-u 0 C-l $B$H%?%$%W$7$^$9!#(B - - >> C-h k C-f $B$H%?%$%W$7$J$5$$!#?7$7$$%&%#%s%I%&$,(B C-f $B%3%^%s%I$N%I%-(B - $B%e%a%s%H$rI=<($9$k$?$a$K8=$l$k$HF1;~$K!"$3$N%&%#%s%I%&$,$I$N$h$&(B - $B$K=L$`$+$r4Q;!$7$J$5$$!#(B - - >> C-x 1$B$H%?%$%W$7$F!"%I%-%e%a%s%H$N8=$o$l$F$$$?%&%#%s%I%&$r>C$7$J$5(B - $B$$!#(B - -$BA^F~$H:o=|(B -========== - - $B%F%-%9%H$r%?%$%W$7$?$1$l$P!"C1$K$=$l$r%?%$%W$9$k$@$1$G9=$$$^$;$s!#L\$K(B -$B8+$($kJ8;z!J(B'A','7','*','$B$"(B'$B$J$I!K$O(BEmacs$B$K$h$C$F%F%-%9%H$G$"$k$H$_$J$5$l!"(B -$B$=$N$^$^A^F~$5$l$^$9!#9T$N=*$o$j$O2~9TJ8;z$GI=$5$l!"$3$l$rF~NO$9$k$K$O(B - $B$r%?%$%W$7$^$9!#(B - - $BD>A0$KF~NO$7$?J8;z$r:o=|$9$k$K$O!"(B $B$rF~NO$7$^$9!#(B $B$O!"(B -$B%-!<%\!<%I$G!V(BDelete$B!W$H=q$$$F$"$k%-!<$r2!$7$FF~NO$7$^$9!#!V(BDelete$B!W$N$+$o(B -$B$j$K!V(BRubout$B!W$H=q$$$F$"$k$+$bCN$l$^$;$s!#$h$j0lHLE*$K$O!"(B $B$O!"8=:_(B -$B%+!<%=%k$N$"$k0LCV$ND>A0$NJ8;z$r:o=|$7$^$9!#(B - - >> $BJ8;z$r$$$/$D$+%?%$%W$7!"$=$l$+$i$=$l$i$r(B $B$r;H$C$F:o=|$7(B - $B$J$5$$!#(B - - >> $B1&%^!<%8%s$r1[$($k$^$G%F%-%9%H$r%?%$%W$7$J$5$$!#%F%-%9%H$,0l9T$N(B - $BI}0J>e$KD9$/$J$k$H!"$=$N9T$O2hLL$+$i$O$_=P$7$F!V7QB3!W$5$l$^$9!#(B - $B1&C<$K$"$k(B'\'$B5-9f$O!"$=$N9T$,7QB3$5$l$F$$$k$3$H$rI=$7$F$$$^$9!#(B - Emacs$B$O!"8=:_JT=8Cf$N0LCV$,8+$($k$h$&$K9T$r%9%/%m!<%k$7$^$9!#2hLL(B - $B$N1&$"$k$$$O:8$NC<$K$"$k(B'\'$B5-9f$O!"$=$NJ}8~$K9T$,$^$@B3$$$F$$$k$3(B - $B$H$rI=$7$F$$$^$9!#(B - - $B$3$l$O!"J8>O$G@bL@$9$k$h$j> $B@h$[$IF~NO$7$?!"7QB3$5$l$?9T$N>e$K%+!<%=%k$r$b$C$F$$$-!"(BC-d $B$G%F(B - $B%-%9%H$r:o=|$7$F!"%F%-%9%H$,0l9T$K<}$^$k$h$&$K$7$F$_$J$5$$!#7QB3(B - $B$rI=$9(B'\'$B5-9f$O>C$($^$7$?$M!#(B - - >> $B%+!<%=%k$r9T$N@hF,$K0\F0$7!"(B $B$rF~NO$7$J$5$$!#$3$l$O$=$N9T(B - $B$ND>A0$N9T6g@Z$j$r:o=|$9$k$N$G!"$=$N9T$,A0$N9T$H$D$J$,$C$F$7$^$$(B - $B$^$9!#$D$J$,$C$?9T$,2hLL$NI}$h$jD9$/$J$k$H!"7QB3$NI=<($,$5$l$k$G(B - $B$7$g$&!#(B - - >> $B$r2!$7$F!"$b$&0lEY9T6g@Z$j$rA^F~$7$J$5$$!#(B - - Emacs$B$N$[$H$s$I$N%3%^%s%I$O!"7+$jJV$7$N2s?t$rM?$($k$3$H$,$G$-$^$9!#$3(B -$B$N$3$H$O!"J8;z$NA^F~$K$D$$$F$bEv$F$O$^$j$^$9!#(B - - >> C-u 8 * $B$HF~NO$7$F$_$J$5$$!#$I$&$J$j$^$7$?$+!#(B - - $BFs$D$N9T$N4V$K6uGr9T$r:n$j$?$$>l9g$K$O!"FsHVL\$N9T$N@hF,$K9T$-!"(BC-o $B$r(B -$BF~NO$7$^$9!#(B - - >> $BE,Ev$J9T$N@hF,$K9T$-!"$=$3$G(B C-o $B$rF~NO$7$F$_$J$5$$!#(B - - $B$3$l$G!"(BEmacs$B$G!"%F%-%9%H$rF~NO$7!"$^$?4V0c$$$r=$@5$9$k$b$C$H$b4pK\E*(B -$B$JJ}K!$r3X$s$@$3$H$K$J$j$^$9!#J8;z$HF1$8MM$K!"C18l$d9T$b:o=|$9$k$3$H$,$G$-(B -$B$^$9!#:o=|A`:n$K$D$$$FMWLs$9$k$H $B%+!<%=%k$ND>A0$NJ8;z$r:o=|(B - C-d $B%+!<%=%k$N$"$kJ8;z$r:o=|(B - - ESC $B%+!<%=%k$ND>A0$NC18l$r:o=|(B - ESC d $B%+!<%=%k0LCV0J9_$K$"$kC18l$r:o=|(B - - C-k $B%+!<%=%k0LCV$+$i9TKv$^$G$r:o=|(B - - $B2?$+$r:o=|$7$?8e$G!"$=$l$r85$KLa$7$?$/$J$k$3$H$,$"$j$^$9!#(BEmacs$B$O!"0l(B -$BJ8;z$h$j$bBg$-$$C10L$G:o=|$r9T$C$?;~$K$O!":o=|$7$?FbMF$rJ]B8$7$F$*$-$^$9!#(B -$B85$KLa$9$K$O!"(BC-y $B$r;H$$$^$9!#Cm0U$7$?$$$N$O!"(BC-y $B$r:o=|$r9T$C$?>l=j$@$1$G(B -$B$O$J$/!"$I$3$K$G$b=PMh$k$3$H$G$9!#(BC-y $B$O!"J]B8$5$l$?%F%-%9%H$r8=:_%+!<%=%k(B -$B$N$"$k>l=j$KA^F~$9$k$?$a$N%3%^%s%I$G$9$+$i!"$3$l$r;H$C$F%F%-%9%H$N0\F0$r9T(B -$B$&$3$H$,$G$-$^$9!#(B - - $B:o=|$r9T$&%3%^%s%I$K$O!"(B"Delete" $B%3%^%s%I$H!"(B"Kill" $B%3%^%s%I$H$,$"$j$^(B -$B$9!#(B"Kill" $B%3%^%s%I$G$O:o=|$5$l$?$b$N$OJ]B8$5$l$^$9$,!"(B"Delete" $B%3%^%s%I$G(B -$B$OJ]B8$5$l$^$;$s!#$?$@$7!"7+$jJV$72s?t$,M?$($i$l$k$H!"J]B8$5$l$^$9!#(B - - >> C-n $B$r#22s$[$I%?%$%W$7$F!"2hLL$NE,Ev$J>l=j$K0\F0$7$J$5$$!#$=$7$F!"(B - C-k $B$G!"$=$N9T$r:o=|$7$J$5$$!#(B - - $B0l2sL\$N(B C-k $B$G$=$N9T$NFbMF$,:o=|$5$l!"$b$&0lEY(B C-k $B$rF~NO$9$k$H!"$=$N(B -$B9T<+?H$,:o=|$5$l$^$9!#$b$7!"(BC-k $B$K7+$jJV$72s?t$r;XDj$7$?>l9g$K$O!"$=$N2s?t(B -$B$@$1$N9T$,!JFbMF$H9T<+?H$H$,F1;~$K!K:o=|$5$l$^$9!#(B - - $B:#:o=|$5$l$?%F%-%9%H$O!"J]B8$5$l$F$$$k$N$G!"$=$l$r> C-y $B$r;n$7$F$_$J$5$$!#(B - - C-k $B$r2?EY$bB3$1$F9T$&$H!":o=|$5$l$k%F%-%9%H$O!"$^$H$a$FJ]B8$5$l!"(BC-y -$B$G!"$=$NA4$F$,> C-k $B$r2?EY$b%?%$%W$7$F$_$J$5$$!#(B - - >> $B%F%-%9%H$r$N%F%-%9%H$r:o=|$9$k$H$I$&(B -$B$J$k$G$7$g$&$+!#(BC-y $B$O!"$b$C$H$b:G6a:o=|$5$l$?$b$N$r> $B9T$r:o=|$7!"%+!<%=%k$r0\F0$5$;!"JL$N9T$r:o=|$7$J$5$$!#(BC-y $B$r9T$&(B - $B$H!"#2HVL\$N9T$,F@$i$l$^$9!#(B - -$BC$7(B(UNDO) -============== - - $B$$$D$G$b!"%F%-%9%H$rJQ99$7$?$1$l$I$b!"$=$l$r$b$H$KLa$7$?$$$H$-$O(BC-x u -$B$GD>$j$^$9!#IaDL$O4V0c$($?%3%^%s%I$rL58z$K$9$kF/$-$r$7$^$9!#7+$jJV$7$F(BUNDO -$B$r9T$J$*$&$H$9$k;~$O!"2?EY$b$=$N%3%^%s%I$r9T$J$($P=PMh$k$h$&$K$J$C$F$$$^$9!#(B - - >> $B$3$N9T$r(BC-k$B$G>C$7$F2<$5$$!#$=$7$F!"(BC-x u$B$GLa$7$F2<$5$$!#(B - - C-_$B$O!"(BUNDO$B$r9T$J$&!"$b$&0l$D$N%3%^%s%I$G$9!#5!G=$O!"(BC-x u$B$HF1$8$G$9!#(B - - C-_$B$d(BC-x u$B$K(BUNDO$B$N2s?t$r!"M?$($k$3$H$,=PMh$^$9!#(B - - -$B%U%!%$%k(B -======== - - $B%F%-%9%H$X$NJQ99$r1J5WE*$K$9$k$?$a$K$O!"$=$l$r%U%!%$%k$KJ]B8$7$J$1$l$P(B -$B$J$j$^$;$s!#J]B8$5$l$J$$$H!"$[$I$3$7$?JQ99$O!"(BEmacs$B$r=*N;$9$k$HF1;~$K<:$o$l(B -$B$F$7$^$$$^$9!#(B - - $B$$$^8+$F$$$k%U%!%$%k$KBP$7$F!"$"$J$?$NJT=8$r9T$C$?$b$N$r=q$-9~$_$^$9!#(B -$B$$$^8+$F$$$k%U%!%$%k$H$O!"4JC1$K$$$($PJT=8$7$F$$$k%U%!%$%k<+BN$N$3$H$G$9!#(B - - $B$"$J$?$,%U%!%$%k$r%;!<%V!JJ]B8$9$k!K$9$k$^$G!":#$^$G$NJQ99$OJT=8$7$F$$(B -$B$k%U%!%$%k$K=q$-9~$^$l$k;v$O$"$j$^$;$s!#$=$l$O!"$"$J$?$,$=$N$h$&$K9T$$$?$/(B -$B$J$$$N$K!"ESCf$^$GJQ99$r2C$($?$b$N$,>!A0(B -$B$rJQ$($F%*%j%8%J%k$N%U%!%$%k$r;D$7$^$9!#(B - -$BHw9M(B: $B$^$?!"(BEmacs$B$OITB,$N;vBV$KBP$7!"0lDj$N%?%$%_%s%0$4$H$K<+F0E*(B - $B$KJT=8$7$F$$$k%U%!%$%k$NFbMF$rL>A0$rJQ$($?%U%!%$%k$K%;!<%V$7(B - $B$^$9!#$3$l$K$h$C$F!"K|0l$N>l9g$O9T$C$?$NJQ99$KBP$7:G>.8B$NHo(B - $B32$G:Q$`$h$&$K$J$C$F$$$^$9!#(B - - $B2hLL$N2<$NJ}$r8+$k$H!"$3$N$h$&$J46$8$G%b!<%I%i%$%s$,I=<($5$l$F$$$k$H;W(B -$B$$$^$9!#(B - - -($BNc(B) [--]J:--**-Mule: MULE.tut (Fundamental) ---55%-------------- - - - $B$3$N(BEmacs$B%A%e!<%H%j%"%k$N%3%T!<$O(BMULE.tut$B$H8F$P$l$F$$$^$9!#%U%!%$%k$r(B -$B%U%!%$%s%I!J%U%!%$%k$r8+$D$1$F%P%C%U%!$KFI$_9~$`$3$H!K$9$k$H!"(BMULE.tut$B$NIt(B -$BJ,$KI=<($5$l$^$9!#Nc$($P!"(Bnew-file$B$H$$$&L>A0$N%U%!%$%k$r%U%!%$%s%I$7$?$J$i(B -$B$P!"(B"Mule: new-file"$B$H$$$&%b!<%I%i%$%s$K$J$k$G$7$g$&!#(B - -$BCm0U!'(B $B%b!<%I%i%$%s$K$D$$$F$O8e$[$I@bL@$7$^$9!#>/$7$*BT$A$r!#(B - - $B%U%!%$%k$r%U%!%$%s%I$7$?$j!"%;!<%V$7$?$j$9$k%3%^%s%I$O!"$3$l$^$G$N$b$N(B -$B$H$O0c$$!"#2$D$NJ8;z$+$i$J$C$F$$$^$9!#(BC-x $B$KB3$$$FF~NO$9$kJ8;z$,!"%U%!%$%k(B -$B$KBP$7$F9T$&A`:n$rI=$7$^$9!#(B - - $B$b$&0l$D$3$l$^$G$N$b$N$H0c$&E@$O!"%U%!%$%s%I$N;~!"%U%!%$%kL>$r(BEmacs$B$K(B -$BLd$o$l$^$9!#$3$N$3$H$r!"Cl9g$O%U%!%$%kL>$G$9!#(B - - C-x C-f $B%U%!%$%k$r8+$D$1$k!J%U%!%$%s%I$9$k!K(B - - Emacs$B$O%U%!%$%kL>$rJ9$$$F$-$^$9!#$=$l$O!"2hLL$N2<$N9T$K8=$l$^$9!#%U%!(B -$B%$%kL>$r;XDj$7$F$$$kItJ,$O!"%_%K%P%C%U%!$H8F$P$l$k$b$N$G$9!#%_%K%P%C%U%!$O(B -$B$3$NMM$J;H$o$lJ}$r$7$^$9!#%U%!%$%kL>$KB3$$$F!"%j%?!<%s%-!<$r2!$9$H!"%_%K%P(B -$B%C%U%!$KI=<($5$l$F$$$?FbMF$O$b$&I,MW$G$O$J$/$J$k$N$G>C$($F$7$^$$$^$9!#(B - - >> C-x C-f$B$H%?%$%W$7$?8e$K(BC-g$B$H%?%$%W$7$F2<$5$$!#%_%K%P%C%U%!$NFbMF(B - $B$rC$7!"$^$?!"(BC-x C-f$B%3%^%s%I$bC$7$^$9!#$H8@$&Lu$G!"2?$b(B - $B%U%!%$%k$r8+$D$1$k$h$&$J$3$H$O$7$^$;$s!#(B - - $B:#EY$O%U%!%$%k$r%;!<%V$7$F$_$^$7$g$&!#:#$^$G$NJQ99$rJ]B8$9$k$?$a$K$OA0$r$D$1$i$l$F;D$5$l$F$$$k$N$GFbMF$O<:$o$l$^$;$s!#$=(B -$B$N?7$7$$L>A0$O%*%j%8%J%k$N%U%!%$%k$NL>A0$K(B'~'$B$r$D$1$?$b$N$G$9!#(B - - $B%;!<%V$,=*$o$k$H!"(BEmacs$B$O%;!<%V$7$?%U%!%$%k$NL>A0$rI=<($7$^$9!#(B - - >> C-x C-s$B$H%?%$%W$7$F%A%e!<%H%j%"%k$N%3%T!<$r%;!<%V$7$F2<$5$$!#$=$N(B - $B;~!"2hLL$N2<$NJ}$K(B"Wrote ...../MULE.tut"$B$HI=<($5$l$^$9!#(B - - $B?7$7$$%U%!%$%k$r:n$k;~!"$"$?$+$b0JA0$+$i$"$C$?%U%!%$%k$r%U%!%$%s%I$9$k(B -$B$h$&$J%U%j$r$7$^$9!#$=$&$7$F!"$=$N%U%!%$%s%I$7$?%U%!%$%k$K%?%$%W$7$F$$$-$^(B -$B$9!#(B - - $B%U%!%$%k$r%;!<%V$7$h$&$H$7$?;~$K=i$a$F!"(BEmacs$B$O:#$^$GJT=8$7$F$$$?FbMF(B -$B$r%U%!%$%k$NCf$K=q$-9~$_$^$9!#(B - - -$B%P%C%U%!(B -======== - - $B$b$7!"#2HVL\$N%U%!%$%k$r(B C-x C-f $B$G> C-x C-b $B$H%?%$%W$7$J$5$$!#$=$l$>$l$N%P%C%U%!$,$I$N$h$&$KL>A0$r;}(B - $B$C$F$$$k$+!"$=$7$F!"$I$N$h$&$J%U%!%$%kL>$r$D$1$F$$$k$N$+4Q;!$7$J(B - $B$5$$!#(B - - $B%P%C%U%!$K$O%U%!%$%k$H0lCW$J$$$b$N$b$"$j$^$9!#$?$H$($P!"(B -"*Buffer List*" $B$H$$$&%U%!%$%k$O$"$j$^$;$s!#$3$l$O(B C-x C-b $B$K$h$C$F:n$i$l(B -$B$?%P%C%U%!%j%9%H$KBP$7$F$N%P%C%U%!$G$9!#(B - - $B$"$J$?$,8+$F$$$k(BEmacs$B%&%#%s%I%&Fb$K$"$k!"$I$s$J%F%-%9%H$G$b!"$$$:$l$+(B -$B$N%P%C%U%!Fb$K$"$j$^$9!#(B - - >> $B%P%C%U%!%j%9%H$r>C$9$?$a(B C-x 1 $B$H%?%$%W$7$J$5$$!#(B - - $B$b$7!"$"$k%U%!%$%k$N%F%-%9%H$KJQ99$r9T$J$C$F$+$i!"B>$N%U%!%$%k$rA0$K$h$k3HD%!#B3$1$F%3%^%s%I$NL>A0$rF~NO$7$^$9!#(B - - $B$3$l$i$O0lHL$K!"JXMx$@$1$l$I$b!"$3$l$^$G8+$F$-$?$b$N$[$IIQHK$K$OMQ$$$i(B -$B$l$J$$%3%^%s%I$N$?$a$N$b$N$G$9!#(BC-x C-f $B!J%U%!%$%s%I!K$d(B C-x C-s$B!J%;!<%V!K(B -$B$O$3$NCg4V$G$9!#B>$K!"(BC-x C-c$B!J%(%G%#%?$N=*N;!K$b$=$&$G$9!#(B - - C-z$B$O(BEmacs$B$rH4$1$k$N$KNI$/;H$o$l$kJ}K!$G$9!#(BEmacs$B$r=*N;$9$k$3$H$J$/!"(B -$B0lC6!"(Bcsh$B$N%l%Y%k$KLa$k$K$O0lHVNI$$J}K!$H8@$($k$G$7$g$&!#(BC-z$B$r9T$J$o$l$F$b(B -Emacs$B$O%9%H%C%W$7$F$$$k$@$1$G!"FbMF$,GK2u$5$l$k$H$$$&$3$H$O$"$j$^$;$s!#(B - -$BCm0U(B: $B$?$@$7(BX-window$B$G9T$J$C$F$$$k>l9g!"$b$7$/$O;HMQ$7$F$$$k%7%'%k(B - $B$,(Bsh$B$N;~$O!"$3$N8B$j$G$O$"$j$^$;$s!#(B - - - C-x $B%3%^%s%I$O!"$?$/$5$s$"$j$^$9!#$9$G$K3X$s$@$b$N$O0J2<$N$b$N$G$9!#(B - - C-x C-f $B%U%!%$%k$NJT=8!J(BFind$B!K(B - C-x C-s $B%U%!%$%k$NJ]B8!J(BSave$B!K(B - C-x C-b $B%P%C%U%!%j%9%H$NI=<((B - C-x C-c $B%(%G%#%?$r=*N;$9$k!#%U%!%$%k$NJ]B8$O!"<+F0E*$K$O9T$o$l$^$;(B - $B$s!#$7$+$7!"$b$7%U%!%$%k$,JQ99$5$l$F$$$l$P!"%U%!%$%k$NJ]B8(B - $B$r$9$k$N$+$I$&$+$rJ9$$$F$-$^$9!#J]B8$7$F=*N;$9$kIaDL$NJ}K!(B - $B$O!"(BC-x C-s C-x C-c $B$H$9$k$3$H$G$9!#(B - - $BL>A0$K$h$k3HD%%3%^%s%I$K$O!"$"$^$j;H$o$l$J$$$b$N$d!"FCDj$N%b!<%I$G$7$+(B -$B;H$o$J$$$b$N$J$I$,$"$j$^$9!#Nc$H$7$F!"(B"command-apropos" $B$r$H$j$"$2$^$9!#$3(B -$B$N%3%^%s%I$O%-!<%o!<%I$rF~NO$5$;!"$=$l$K%^%C%A$9$kA4$F$N%3%^%s%I$NL>A0$rI=(B -$B<($7$^$9!#(BESC x $B$H%?%$%W$9$k$H!"%9%/%j!<%s$N2<$K(B "M-x" $B$,I=<($5$l$^$9!#$3$l(B -$B$KBP$7$F!"A0!J:#$N>l9g!"(B"command-apropos"$B!K$rF~NO$7$^$9!#(B -"command-a" $B$^$GF~NO$7$?8e%9%Z!<%9$rF~$l$l$P!"8e$NItJ,$O<+F0E*$KJd$o$l$^$9!#(B -$B$3$N8e!"%-!<%o!<%I$rJ9$+$l$^$9$+$i!"CN$j$?$$J8;zNs$r%?%$%W$7$^$9!#$J$*!"%-!<(B -$B%o!<%I$rF~$l$J$$$H!"A4$F$N%3%^%s%I$,I=<($5$l$^$9!#(B - - >> ESC x $B$r%?%$%W$7!"B3$1$F!"(B"command-apropos" $B$"$k$$$O(B - "command-a" $B$H%?%$%W$7$^$9!#" - $B$H%?%$%W$7$^$9!#(B - - $B8=$l$?!V%&%#%s%I%&!W$r>C$9$K$O!"(BC-x 1 $B$H%?%$%W$7$^$9!#(B - -$B%b!<%I%i%$%s(B -============ - - $B$b$7$f$C$/$j$H%3%^%s%I$rBG$C$?$J$i$P!"2hLL$N2l=j$KBG$C$?$b$N$,I=<($5$l$^$9!#%(%3!<%(%j%"$O2hLL$N(B1$B$P$s2<$N9T$G$9!#$=$N(B -$B$9$0>e$N9T$O!"%b!<%I%i%$%s$H8F$P$l$F$$$^$9!#%b!<%I%i%$%s$O$3$s$JIw$KI=<($5(B -$B$l$F$$$k$G$7$g$&!#(B - - [--]J:--**-Mule: MULE.tut (Fundamental) ---NN%-------------- - - -$BCm0U(B: NN%$B$N(BNN$B$O?t;z$,F~$C$F$$$^$9!#$"$J$?$,;H$C$F$$$k(BEmacs$B$N%b!<(B - $B%I%i%$%s$H0c$&$+$bCN$l$J$$$1$I!"92$F$J$$$h$&$K!#Nc$($P!";~4V(B - $B$d(Buptime$B$,I=<($5$l$F$$$k$N$O!"(Bdisplay-time$B$H$$$&5!G=$,F0$$$F(B - $B$$$k$+$i$G$9!#(B - - $B$3$N9T$K$h$C$FB?$/$NM-MQ$J>pJs$,F@$i$l$^$9!#(B - - - $B:#!"$"$J$?$,8+$F$$$k%U%!%$%kL>$rI=<($7$F$$$^$9!#(BNN%$B$O8=:_%9%/%j!<%s>e(B -$B$K%U%!%$%k$N0lHV>e$+$i2?%Q!<%;%s%HL\$,I=<($5$l$F$$$k$+$r<($7$F$$$^$9!#%U%!(B -$B%$%k$N0lHV:G=i$rI=<($7$F$$$k$J$i$P!"(B--Top--$B$HI=<($5$l$F$^$9!#%U%!%$%k$N0lHV(B -$B:G8e$rI=<($7$F$$$k$J$i$P!"(B--Bot--$B$HI=<($5$l$^$9!#2hLL$NCf$K%U%!%$%k$NA4$F$,(B -$BI=<($5$l$F$$$k$J$i$P!"(B--All--$B$HI=<($5$l$^$9!#(B - - $B%b!<%I%i%$%s$N>.3g8L$NCf$O!":#$I$s$J%b!<%I$KF~$C$F$$$k$+$r<($7$F$$$^$9!#(B -$B8=:_$O!"%G%U%)%k%H$N(BFundamental$B$KF~$C$F$$$^$9!#$3$l$b%a%8%c!<%b!<%I$N0lNc$G(B -$B$9!#(B - - Emacs$B$O(BLisp mode$B$d(BText mode$B$N$h$&$J$3$H$J$k%W%m%0%i%`8@8l$d%F%-%9%H$K(B -$BBP$7$F%(%G%#%C%H$r9T$&$?$a$N4v$D$+$N%a%8%c!<%b!<%I$r;}$C$F$$$^$9!#$I$s$J;~(B -$B$G$bI,$:$$$:$l$+$N%a%8%c!<%b!<%I$N>uBV$K$J$C$F$$$^$9!#(B - - $B$=$l$>$l$N%a%8%c!<%b!<%I$O4v$D$+$N%3%^%s%I$rA4$/0c$&?6$kIq$$$K$7$F$7$^(B -$B$$$^$9!#Nc$r>e$2$F$_$^$7$g$&!#%W%m%0%i%`$NCf$K%3%a%s%H$r:n$k%3%^%s%I$,$"$j(B -$B$^$9!#%3%a%s%H$r$I$NMM$J7A<0$K$9$k$+$O!"3F%W%m%0%i%`8@8l$K$h$C$F0c$$$^$9$,!"(B -$B$=$l$>$l$N%a%8%c!<%b!<%I$O!"$-$A$s$HF~$l$F$/$l$^$9!#(B - - $B$=$l$>$l$N%a%8%c!<%b!<%I$KF~$k$?$a$N%3%^%s%I$O%b!<%IL>$N3HD%$5$l$?$b$N(B -$B$K$J$C$F$$$^$9!#Nc$($P!"(BM-x fundamental-mode$B$O(BFundamental$B$KF~$k$?$a$N$b$N$G(B -$B$9!#(B - - $B$b$7!"1Q8l$r%(%G%#%C%H$9$k$J$i$P!"(BText mode$B$KF~$j$^$9!#(B - - >> M-x text-mode $B$H%?%$%W$7$J$5$$!#(B - - $B8=:_$N%a%8%c!<%b!<%I$K$D$$$F$N%I%-%e%a%s%H$r8+$?$$;~$O!"(BC-h m$B$H%?%$%W(B -$B$7$^$9!#(B - - >> C-h m $B$r;H$C$F(BText mode$B$H(BFundamental mode$B$N0c$$$rD4$Y$J$5$$!#(B - - >> C-x 1$B$G%I%-%e%a%s%H$r2hLL$+$i>C$7$J$5$$!#(B - - $B:8C<$N(B '[--]' $B$O8=:_$N%-!\$7$$@bL@$O(B -$B!V$?$^$4!W$N%^%K%e%"%k$rD4$Y$F2<$5$$!#(B - - $B$=$N$9$01&$K$O%3!<%IBN7O(B (coding-system) $B$K4X$9$k%U%i%0$N>uBV$,I=(B -$B<($5$l$F$$$^$9!#(BMule $B$O!"%U%!%$%kF~=PNO!"F~NO!"2hLL=PNO$K$D$$$F!"$=$l$>$lFH(B -$BN)$K%3!<%IBN7O$r;XDj$5$;$k$3$H$,=PMh$^$9$,!"DL>o$O%U%!%$%kMQ$N%3!<%IBN7O$N(B -$B%K!<%b%K%C%/$N$_I=<($7$F$$$^$9!#(B - - >> $B%b!<%I%i%$%s>e$K(B"J:","S:",$B$b$7$/$O(B "E:"$B$,I=<($5$l$F$$$k$+$I$&$+3N(B - $BG'$7$J$5$$!#(B - - $B:G=i$N0lJ8;z$,%3!<%IBN7O$N%K!<%b%K%C%/!"> C-x C-k t$B$r(B2$BEY9T$$$J$5$$!#(B - - $BF~NO%b!<%I$,(BJIS$B%3!<%I$N@_Dj$H$J$C$F$$$k;~!"$b$7$"$J$?$N;H$C$F$$$kC$B$b(BM-<$BJ8;z(B>$B$bF1$8F/$-$r$7$^$9!#:#$^$G$N@bL@$G(BESC -<$BJ8;z(B>$B$H9T$J$C$F$$$?$H$3$m$,!"(BM-<$BJ8;z(B>$B$H$J$j$^$9!#Cm0U$7$J$1$l$P$J$i$J$$$N(B -$B$O!"%7%U%H(BJIS$B$d(BEUC$B%3!<%I$N;~$O;HMQ$G$-$^$;$s!#(B - - $B%3!<%IBN7O$N$N@Z$jBX$($O!"3F!9$N%P%C%U%!$KBP$7$F$N$_M-8z$G$9!#$=$l$>$l(B -$B$N!"%3!<%IBN7O;XDj$K$D$$$F$O!"(BC-h a coding-system $B$G8+$k$3$H(B -$B$,=PMh$^$9!#(B - - >> C-h a coding-system $B$G=P$F$/$k%I%-%e%a%s%HCf$N!"(B - set-display-coding-system, set-file-coding-system, - set-process-coding-system $B$N@bL@$rFI$_$J$5$$!#(B - -$B8!:w(B -===== - - $BJ8;zNs$r!"%U%!%$%kFb$G!"A0J}Kt$O8eJ}$K!"C5$9;v$,$G$-$^$9!#8!:w$r;O$a$k(B -$B%3%^%s%I$O!"%+!<%=%k0LCV0J9_$r8!:w$9$k$J$i$P(B C-s$B!"%+!<%=%k0LCV0JA0$J$i$P(B -C-r $B$G$9!#(BC-s $B$r%?%$%W$9$k$H!"%(%3!<%(%j%"$K(B "I-search:"$B$H$$$&J8;zNs$,%W%m(B -$B%s%W%H$H$7$FI=<($5$l$^$9!#(BESC$B$r2!$9$H!"=*N;$G$-$^$9!#(B - - - >> C-s$B$G8!:w$,;O$^$j$^$9!#$=$l$+$i!"$f$C$/$j$H#1J8;z$:$D(B"cursor"$B$H$$(B - $B$&C18l$rF~NO$7$^$9!##1J8;zF~NO$9$k$4$H$K!"%+!<%=%k$O!"$I$s$JF0$-(B - $B$r$7$^$9$+(B? - - >> $B$b$EY(B C-s $B$r%?%$%W$9$k$H!"> $B$r#42sF~NO$7$F!"%+!<%=%k$NF0$-$r8+$J$5$$!#(B - - >> ESC$B$r2!$7$F!"=*N;$7$^$9!#(B - - $BC5$7$?$$J8;zNs$r%?%$%WCf$G$b!"%?%$%W$7$?J8;zItJ,$@$1$G!"8!:w$r;O$a$^$9!#(B -$B$B$rF~NO$9$k$H!"8!:wJ8;zNs$N#1HV8e$m$NJ8;z$,>C$($^$9!#(B -$B$=$7$F!"%+!<%=%k$O!"A02s$N0LCV$KLa$j$^$9!#$?$H$($P!"(B"cu"$B$H%?%$%W$7$F!":G=i(B -$B$N(B"cu"$B$N0LCV$K%+!<%=%k$,F0$$$?$H$7$^$9!#$3$3$G(B$B$rF~NO$9$k$H!"%5!<%A(B -$B%i%$%s$N(B'u'$B$,>C$(!"%+!<%=%k$O!"(B'u'$B$r%?%$%W$9$kA0$K!"%+!<%=%k$,$"$C$?(B'c'$B$N0L(B -$BCV$K!"0\F0$7$^$9!#(B - - $B8!:wuBV$K(B -$BF~$k$3$H$,$"$j$^$9!#%a%8%c!<%b!<%I$N>.3g8L(B'()'$B$N2s$j$rCf3g8L(B'[]'$B$G0O$s$@$b(B -$B$N$,%b!<%I%i%$%s>e$KI=<($5$l$^$9!#Nc$($P!"(B(Fundamental)$B$HI=<($5$l$kBe$o$j$K(B -[(Fundamental)]$B$N$h$&$K$J$j$^$9!#(B - -$BCm0U(B: $B$3$3$G$O%j%+!<%7%V(B $B%(%G%#%F%#%s%0(B $B%l%Y%k<+BN$K$D$$$F$O@bL@$7(B - $B$^$;$s!#(B - - $B%j%+!<%7%V(B $B%(%G%#%F%#%s%0(B $B%l%Y%k$+$iH4$1$G$k$?$a$K$O!"(BM-x top-level -$B$H%?%$%W$7$^$9!#(B - - >> $B;n$7$F$_$F2<$5$$!#%9%/%j!<%s$NDl$K(B"Back to top level"$B$HI=<($5$l$^(B - $B$9!#(B - - $BK\Ev$O!"$3$N;n$_$,9T$o$l$?;~$O!"$9$G$K%H%C%W%l%Y%k$K$$$?$N$G$9!#(BM-x -top-level$B$O!"2?$b1F6A$rM?$($F$$$^$;$s!#(B - - $B%j%+!<%7%V(B $B%(%G%#%F%#%s%0(B $B%l%Y%k$+$iH4$1=P$k$N$KBP$7$F$O(BC-g$B$O8z$-$^$;(B -$B$s!#(B - - -$B%X%k%W(B -====== - - Emacs$B$K$O!"$?$/$5$s$NLr$KN)$D5!G=$,$"$j!"$3$3$G!"$9$Y$F$r@bL@$9$k$3$H(B -$B$O!"IT2DG=$G$9!#$7$+$7!"$^$@CN$i$J$$B?$/$N5!G=$r3X$V$?$a$K$O!"(B$B$H8F$P(B -$B$l$k(B C-h $B$r%?%$%W$9$k$3$H$G!"$?$/$5$s$N>pJs$rC$9(B -$B$3$H$,$G$-$^$9!#(B - - $B:G$b4pK\E*$J$b$N$O!"(BC-h c $B$G$9!#$3$l$KB3$$$F%-!<$rF~NO$9$k$H!"$=$N%3%^(B -$B%s%I$K$D$$$F$NC;$$@bL@$rI=<($7$^$9!#(B - - >> C-h c C-p $B$H%?%$%W$7$F$_$J$5$$!#(B"C-p runs the command previous- - line"$B$N$h$&$J%a%C%;!<%8$,I=<($5$l$k$O$:$G$9!#(B - - $B8+$?$3$H$O$"$k$,!"3P$($F$O$$$J$$%3%^%s%I$b;W$$=P$;$k$N$G$9!#(BC-x C-s $B$N(B -$B$h$&$JJ#?t$G#1$D$N%3%^%s%I$b(BC-h c $B$N8e$m$KB3$1$i$l$^$9!#(B - - $B$b$C$H>\$7$/CN$j$?$+$C$?$i!"(Bc $B$NBe$o$j$K(B k $B$r;XDj$7$^$9!#(B - - >> C-h k C-p $B$H%?%$%W$7$F$_$J$5$$!#(B - - Emacs$B$N%&%#%s%I%&$K!"%3%^%s%I$NL>A0$H5!G=$,I=<($5$l$^$9!#FI$_=*$($?$i!"(B -C-x 1 $B$H%?%$%W$9$k$H!"H4$1$i$l$^$9!#(B - - $BB>$K$bLr$KN)$D%*%W%7%g%s$,$"$j$^$9!#(B - - C-h f $B%U%!%s%/%7%g%sL>$rF~NO$9$k$H!"%U%!%s%/%7%g%s$rI=<($7$^$9!#(B - - >> C-h f previous-line $B$r%?%$%W$7!"(B $B$r2!$7$J$5$$!#(BC-p $B%3%^%s(B - $B%I$rpJs$rI=<($7$^$9!#(B - - C-h a $B%-!<%o!<%I$rF~NO$9$k$H!"L>A0$K$=$N%-!<%o!<%I$r4^$`!"A4$F$N%3(B - $B%^%s%I$rI=<($7$^$9!#$3$l$i$N%3%^%s%I$O$9$Y$F(BESC x $B$G> C-h a file $B$H%?%$%W$7!"(B$B$r2!$7$J$5$$!#L>A0$K(B"file"$B$H$$$&J8(B - $B;z$r;}$DA4$F$N%3%^%s%I$rI=<($7$^$9!#$^$?!"(Bfind-file $B$d(B write-file - $B$H$$$&L>$N(B C-x C-f $B$d(B C-x C-w $B$N$h$&$J%3%^%s%I$bI=<($5$l$^$9!#(B - -$B$*$o$j$K(B -======== - -$BK:$l$:$K!'(B $B=*N;$9$k$K$O!"(BC-x C-c $B$H$7$^$9!#(B - - - $B$3$NF~LgJT$O!"$^$C$?$/$N=i?4o$KB?$/$N$3$H$,$G$-$k>l9g$K$OFC$K$=$&$G$7$g(B -$B$&!#$=$7$F!"(BEMACS $B$G$O!"O$O(BGMW + -Wnn + Nemacs$B$r;H$C$F=q$-$^$7$?!#$=$N$h$&$JAG@2$i$7$$%W%m%0%i%`$r:n$C$?J}!9(B -$B$X46M;R$5$s!"$I$&$b$"$j$,$H$&!#(B - - - - - -$B8mLu!"13!"$=$NB>!"$NJ8@U$O!"0J2<$Nn(B GNUEMACS(Mule) $(C@T9.Fm(B + ============================== + +$(CAV@G(B: $(C@L(B $(C@T9.Fm@:(B, "$(C9h?l1b:84Y(B $(C@Mn(B + $(C@V=@4O4Y(B. ">>" $(C7N:NEM(B $(C=C@[GO4B(B $(CG`@:(B, $(C1W(B $(C6'(B $(C9+>y@;(B $(CGX>_(B + $(CGO4B0!8&(B $(CAv=CGO0m(B $(C@V=@4O4Y(B. + + Mule $(C@G(B $(C8m7I>n8&(B $(C@T7BGR(B $(C6'?!4B(B, $(C@O9]@{@87N(B $(CD\F.7Q(B*$(CE0(B($(CE0(B*$(CEi?!(B, +CTRL $(C6G4B(B, CTL $(C6s0m(B $(C=a@V4Y(B)$(C3*(B $(C8^E8(B*$(CE0(B($(C:8Ek(B, $(C@L=:DI@LGA(B*$(CE08&(B $(C;g?kGQ4Y(B)$(C0!(B +$(C;g?k5K4O4Y(B. $(C1W7!<-(B, CONTROL $(C@L6s5g0!(B META $(C6s0m(B $(C>24B(B $(C4k=E?!(B, $(C4Y@=0z00@:(B +$(C1bH#8&(B $(C;g?kGO4B(B $(C0M@87N(B $(CGU4O4Y(B. + +C-<$(C9.@Z(B> $(CD\F.7Q(B*$(CE08&(B $(C4)8%C$(B, <$(C9.@Z(B>$(CE08&(B $(C4)8(4O4Y(B. $(C?98&(B $(C5i8i(B, + C-f $(C4B(B, $(CD\F.7Q(B*$(CE08&(B $(C4)8#8i<-(B f $(CE08&(B $(C4)8#4B(B $(C0M@;(B + $(C@G9LGU4O4Y(B. +<> + >> $(C1W7/8i(B, C-v (View Next Screen; $(C4Y@=@G(B $(CH-8i@;(B $(C:;4Y(B) $(C8&(B $(CE8@LGA(B + $(CGO?)(B $(C:8< $(C@L=:DI@LGA(B*$(CE08&(B $(C4)8#0m3*<-(B, $(C1W(B $(C5Z(B <$(C9.@Z(B>$(CE08&(B $(C4)8(4O4Y(B. + +$(CAV@G(B: <$(C9.@Z(B>$(C4B(B, $(C4k9.@Z3*(B $(Cn7N<-4B(B $(C00@:(B $(C@G9L0!(B + $(C5K4O4Y(B. $(C8^E8E08&(B $(C;g?kGR(B $(C $(C4k=E?!(B M- + <$(C9.@Z(B> ($(C8^E8E08&(B $(C4)8%C$(B<$(C9.@Z(B>$(CE08&(B $(C4)8%4Y(B) $(C8&(B $(C;g?kGR(B $(C7a=CE00m(B $(C=M@;(B $(C6'4B(B, C-x C-c $(C8&(B $(CE8@LGAGU4O4Y(B. + Emacs$(C8&(B csh$(C7N:NEM(B $(C1b5?GO0m(B $(C@V4B(B $(C0f?l(B, $(C<-=:Ff5eGO4B(B($(C@O=C(B + $(C@{@87N(B $(CA_4\GQ4Y(B)$(CGR(B $(Cz@88i(B, C-v $(C8&(B $(C@T7BGO?)(B $(CAV<U@G(B $(CH-8i0z(B $(C4Y@=(B $(CH-8i?!4B(B, $(CG%=C5G4B(B $(C3;?k?!(B $(C8nG`@G(B $(C9.@L(B $(CA_:95G0m(B +$(C@V=@4O4Y(B. $(CG%=C5G0m(B $(C@V4B(B $(C3;?k@L(B $(C?,n(B $(C@V4B(B $(C0M@;(B $(C>K(B $(CK(B $(CGJ?d0!(B $(C@V=@4O4Y(B. C-v +$(C?!(B $(C@GGO?)(B $(C>U@87N(B $(CAxG`GO4B(B $(C0M@:(B $(C@L9L(B $(C>K>R=@4O4Y(B. $(C?x7!@G(B $(C@Z8.7N(B $(C5G59>F(B +$(C0!4B5%4B(B, ESC v $(C8&(B $(CE8@LGAGU4O4Y(B. + + >> ESC v $(C?M(B C-v $(C8&(B $(C;g?kGO?)(B, $(C@|HD7N(B $(C@L5?GO4B(B $(C0M@;(B $(C8n9x(B $(C=C55GO?)(B + $(C:8<`(B +==== + $(CH-@O@;(B $(CH-8i4\@'7N(B $(C:80m(B $(C0!4B5%4B(B, $(C4Y@=@G(B $(C8m7I>n8&(B $(C;g?kGU4O4Y(B. + + C-v $(C>U@87N(B $(CGQ(B $(CH-8i:P(B $(CAxG`GQ4Y(B + ESC v $(C5Z7N(B $(CGQ(B $(CH-8i:P(B $(C5G59>F0#4Y(B + C-l $(CH-8i@;(B $(C4Y=C>44Y(B. $(C@L(B $(C6'(B, $(C?x7!(B $(CD?<-0!(B $(C@V>z4x(B $(CG`@L(B + $(CH-8i@G(B $(CA_>S?!(B $(C?@557O(B $(CGQ4Y(B + + >> $(CAv1](B $(CD?<-0!(B $(C>n5p?!(B $(C@V4B0!(B, $(C1W(B $(C1YC3?!(B $(C>n62(B $(CEX=:F.0!(B $(C=aA.(B $(C@V4B(B + $(C0!8&(B $(C1b>oGO<n5p7N(B $(C@L5?GO?44B(B + $(C0!(B, $(C1W(B $(C1YC3@G(B $(CEX=:F.4B(B $(C>n6;0T(B $(C5G>z4B0!8&(B $(CA6;gGO?)(B $(C:8<n(B +====================== + + $(CH-8i4\@'@G(B $(C@L5?@:(B $(CGR(B $(Cz=@4O4Y(B. $(C@LA&4B(B, $(CH-8i(B $(C3;?!<-(B, $(CF/(B +$(CA$@G(B $(C@eU(B(forward)$(C5Z(B(backward)$(C7N(B +$(C@L5?GO4B(B $(C8m7I>n8&(B $(C;g?kGO4B(B $(C0M@T4O4Y(B. $(C@L5i@G(B $(C8m7I>n4B(B $(C0"0"(B, C-p, C-n, +C-f, C-b $(C?!(B $(CGR4g5G>n(B $(C@V0m(B, $(CGv@g@G(B $(C@en(B $(C@V@89G7N(B, $(C?\?l1b(B $(C=,?o(B $(C0M@T4O4Y(B. $(C@L5i@:(B, $(C1b:;@{@N(B $(CD?<-@L5?(B $(C8m7I>n@L0m(B +, $(C@ZAV(B $(C;g?kGO4B(B $(C0M@T4O4Y(B. + + >> C-n $(C@;(B $(C8nH8A$55(B $(CE8@LGAGO0m(B, ($(CAv1](B, $(C4g=E@L(B $(C@P0m(B $(C@V4B(B) $(C@L(B $(CG`1n(B + $(CAv(B $(CD?<-8&(B $(C@L5?=CE0<> C-f $(C8&(B $(C;g?kGO?)(B $(CG`@G(B $(CA_0#A$557N(B $(C@L5?GO0m(B, C-p $(C@87N(B $(C8nG`A$55(B + $(C@'7N(B $(C@L5?GO?)(B $(C:8<> $(CG`@G(B $(C<15N?!<-(B C-b $(C8&(B $(CE8@LGAGO?)(B $(C:8<n5p7N(B $(C@L5?GU(B + $(C4O1n(B? $(C4Y=C(B $(CA61](B $(C4u(B C-b $(C8&(B $(CE8@LGAGO0m(B, $(C@L9x@:(B C-f $(C7N(B $(CG`3!(B $(CBJ(B + $(C@87N(B $(C5G59>F0!<n6;0T(B $(C5K4O1n(B? + + + $(CH-8i@G(B $(C<15N3*(B $(C8;9L8&(B $(C3Q>n<-(B $(CD?<-8&(B $(C@L5?=CE07A0m(B $(CGO8i(B, $(C1W(B $(C9fGb?!(B +$(C@V4B(B $(CEX=:F.0!(B $(C@L5?GO?)(B $(C?@0m(B, $(CD?<-4B(B $(CGW;s(B $(CH-8i3;?!(B $(C@V557O(B $(C5K4O4Y(B. + + >> C-n $(C@;(B $(C;g?kGO?)(B, $(CD?<-8&(B $(CH-8i@G(B $(CGO4\:84Y(B $(C9X@87N(B $(C@L5?=CDQ(B $(C:8<<(B + $(C?d(B. $(C9+>y@L(B $(C@O>n334O1n(B? $(CD?<-@G(B $(C@'D!4B(B $(C>n6;0T(B $(C:/GO?4=@4O1n(B? + + $(CGQ9.@Z(B $(C4\@'@G(B $(C@L5?@87N4B(B $(C9x0E7S4Y0m(B $(C;}0"5G8i(B, $(C4\>n4\@'7N(B $(C@L5?GR(B +$(Cn:P(B $(C>U@87N(B $(CAxG`GO0m(B, ESC b $(C7N(B $(CGQ(B $(C4\>n:P(B +$(C@L@|@87N(B $(C5G59>F0)4O4Y(B. + +$(CAV@G(B: $(C@O:;>n?!(B $(C4kGX<-4B(B, $(C4\>n@G(B $(C2w4B(B $(C4\@'@;(B $(C@N=DGR(B $(Cx=@4O(B + $(C4Y88(B, $(C@G;g@{@N(B $(C9.@}@;(B $(C4\>n@G(B $(C2w4B(B $(C4\@'7N<-(B $(CGO0m(B $(C@V=@4O(B + $(C4Y(B. + + >> ESC f $(C3*(B ESC b $(C8&(B $(C8nH8A$55(B $(CE8@LGAGO?)(B $(C:8<$(C4B(B $(C9.<-0|0h@G(B $(CC38.?!(B $(C;g?k5G0m(B, $(CGQFm(B C-<$(C9.@Z(B>$(C4B(B $(C1W0M(B +$(C:84Y55(B $(C4u?m(B $(C1b:;@{@N(B $(C4k;s(B($(C9.@Z6s5g0!(B $(CG`@L6s5g0!(B)$(C?!(B $(C4kGQ(B $(CA6@[?!(B $(C;g?k5K(B +$(C4O4Y(B. + + C-a $(C?M(B C-e $(C55(B $(C>K0m(B $(C@V@88i(B $(CFm8.GQ(B $(C8m7I>n@T4O4Y(B. C-a $(C4B(B $(CD?<-8&(B $(CG`@G(B +$(C<15N7N(B $(C@L5?=CE00m(B, C-e $(C4B(B $(CG`@G(B $(C3!@87N(B $(C@L5?=CE54O4Y(B. + + >> C-a $(C8&(B 2$(CH8(B, $(C1W8.0m3*<-(B C-e $(C8&(B 2$(CH8(B $(C@T7BGO?)(B $(C:8<n8&(B 2$(CH8@L;s(B $(C9]:9GO4u6s55(B, $(CD?<-4B(B $(C1W(B $(C@L;s(B $(C@L5?GOAv(B $(C>J4B(B $(C0M(B + $(C?!(B $(CAV@G(B. + + $(C5N0!Av(B $(C4u(B, $(C0#4\GQ(B $(CD?<-(B $(C@L5?(B $(C8m7I>n0!(B $(C@V=@4O4Y(B. $(CH-@O@G(B $(C<15N7N(B $(C@L5?(B +$(CGO4B(B ESC < $(C?M(B, $(CH-@O@G(B $(C3!@87N(B $(C@L5?GO4B(B ESC > $(C@T4O4Y(B. + + $(CEX=:F.(B $(C3;?!<-(B, $(CD?<-0!(B $(CA8@gGO4B(B $(C@'D!8&(B "$(CFw@NF.(B"$(C6s0m(B $(C:N8(4O4Y(B. $(C9Y2Y(B +$(C>n(B $(C8;GO8i(B, $(CD?<-4B(B, $(CEX=:F.@G(B $(C>n5p?!(B $(C@V4B0!8&(B $(CH-8i@'?!(B $(C3*E83;0m(B $(C@V4B(B $(C0M(B +$(C@T4O4Y(B. + + $(C>F7!?!(B $(C4\`GU4O4Y(B. $(C@L(B $(CA_?!4B(B, $(C4\>n3*(B $(CG`(B +$(C4\@'7N@G(B $(C@L5?8m7I>n55(B $(CFwGT5G>n(B $(C@V=@4O4Y(B. + + C-f $(CGQ(B $(C9.@Z(B $(C>U@87N(B $(CAxG`GQ4Y(B + C-b $(CGQ(B $(C9.@Z(B $(C5Z7N(B $(C5G59>F0#4Y(B + + ESC f $(CGQ(B $(C4\>n(B $(C>U@87N(B $(CAxG`GQ4Y(B + ESC b $(CGQ(B $(C4\>n(B $(C5Z7N(B $(C5G59>F0#4Y(B + + C-n $(C4Y@=(B $(CG`@87N(B $(C@L5?(B + C-p $(C@L@|(B $(CG`@87N(B $(C@L5?(B + + ESC ] $(C4\6t@G(B $(C3!@87N(B $(C@L5?(B + ESC [ $(C4\6t@G(B $(C<15N7N(B $(C@L5?(B + + C-a $(CG`@G(B $(CCVCJ7N(B $(C@L5?(B + C-e $(CG`@G(B $(CCVHD7N(B $(C@L5?(B + + ESC < $(CH-@O@G(B $(CCVCJ7N(B $(C@L5?(B + ESC > $(CH-@O@G(B $(CCVHD7N(B $(C@L5?(B + + >> $(C0"0"@G(B $(C8m7I>n8&(B $(C=C55GO?)(B $(C:8<n4B(B, $(C0!@e(B $(C@ZAV(B + $(C;g?k5G4B(B $(C0M@T4O4Y(B. $(CCVHD@G(B $(C5N0!Av4B(B, $(C@L(B $(C@enAx(B $(C0w@8(B + $(C7N(B $(C@L5?GO1b(B $(C6'9.?!(B, C-v $(C3*(B ESC v $(C8&(B $(C;g?kGO?)(B $(C?)1b7N(B $(C5G59>F(B + $(C?@557O(B $(CGO<n?!4B(B, $(C9]:9H8n8&(B $(C@T7BGO1b(B $(C@|?!(B, C-u +$(C?!(B $(C@L>n<-(B $(C9]:9GO4B(B $(CH8U@87N(B $(C@L5?GU4O4Y(B. + + >> C-n $(CH$@:(B C-p $(C?!(B $(C@{4gGQ(B $(C@N> C-u 3 C-v $(C6s0m(B $(C@T7BGO?)(B $(C:8<F0!4B5%4B(B, C-u 3 ESC v $(C8&(B $(C;g?kGO8i(B $(C5K4O4Y(B. + +$(CA_Av8m7I>n(B +========== + + C-g $(C6s4B(B $(C8m7I>n@L8g(B, $(C@T7B@;(B $(CGJ?d7N(B $(CGO4B(B $(C0M0z(B $(C00@:(B $(C8m7I>n8&(B $(CA_AvGR(B +$(Cn8&(B $(CGQC"(B $(C@T7BGO0m(B $(C@V4B(B $(C55A_?!(B, $(C1W0M@;(B $(CA_AvGO0m(B $(C=M(B +$(C@88i(B, C-g $(C8&;g?kGO8i(B $(C5K4O4Y(B. + + >> C-u 100 $(C8&(B $(CE8@LGAGO?)(B $(C@N`(B, $(C@_8xGO?)(B ESC $(C8&(B $(C@T7BGX(B $(C9v7H@;(B $(C6'55(B, C-g $(C8&(B $(C@T7BGO(B + $(C8i(B $(CCkJ4B(B $(CA6@[@;(B $(CGX9v8.4B(B $(C@{@L(B $(C@V=@4O(B +$(C4Y(B. $(C?98&(B $(C5i8i(B, $(C8m7I>n0!(B $(CA$@G5G>n(B $(C@VAv(B $(C>J4B(B $(CD\F.7Q(B*$(CE08&(B $(C@T7BGX(B $(C9v80(B $(C6'(B +$(C?!4B(B, Emacs$(C4B(B $(C:'@;(B $(C?o8.0m(B, $(C1W8.0m(B, $(CH-8i@G(B $(CA&@O(B $(C9X?!(B, $(C9+>y@L(B $(C3*;&4B(B $(C0!(B +$(C8&(B $(CG%=CGU4O4Y(B. + + Emacs $(C9vA/?!(B $(C5{6s<-4B(B, $(C@L(B $(C@T9.Fm?!(B $(C>2?)A.(B $(C@V4B(B $(C0M@;(B $(C=GG`GR(B $(Cx(B +$(C4B(B $(C0f?l0!(B $(C@V@;(B $(Cn4@(B $(C0M@N0!(B $(C@L5?E08&(B $(C4)8#0m(B, $(C1W(B $(C4Y@=@G(B $(C:N:P@87N(B $(CAxG`GO?)(B $(CAV<n7N:NEM@G(B $(CCb7B@;(B $(CG%=CGO1b(B $(C@'GO(B +$(C?)(B $(C3*E83-(B $(C?):P@G(B $(C@)55?l8&(B $(CAv?l1b(B $(C@'GO?)(B, $(C4Y@=@G(B $(C8m7I>n8&(B $(C>K(B $(CGJ?d0!(B $(C@V=@(B +$(C4O4Y(B. + + C-x 1 $(C@)55?l8&(B 1$(C037N(B $(CGQ4Y(B. + + C-x 1 $(C4B(B, $(C4Y8%(B $(C@)55?l8&(B $(CAv?l0m(B, $(CD?<-0!(B $(C@V4B(B $(C@)55?l8&(B, $(CH-8i@|C<7N(B +$(CH.@eGU4O4Y(B. + + >> $(CD?<-8&(B $(C@L(B $(CG`?!(B $(C0.0m(B $(C?M<-(B, C-u 0 C-l $(C@L6s0m(B $(CE8@LGAGU4O4Y(B. + + >> C-h k C-f $(C6s0m(B $(CE8@LGAGO<n@G(B $(C55(B + $(CE%8UF.8&(B $(CG%=CGO1b(B $(C@'GO?)(B $(C3*E8320z(B $(C5?=C?!(B, $(C@L(B $(C@)55?l0!(B $(C>n6;0T(B + $(CAY>n5e4B0!(B $(C0|B{GO<> C-x 1$(C@L6s0m(B $(CE8@LGAGO0m(B, $(C55E%8UF.0!(B $(C3*E8354x(B $(C@)55?l8&(B $(CAv?l<<(B + $(C?d(B. + +$(C;p@T0z(B $(C;hA&(B +=========== + + $(CEX=:F.8&(B $(CE8@LGAGO0m(B $(C=M@88i(B, $(C4\ $(C@;(B $(CE8@LGAGU4O4Y(B. + + $(CAw@|?!(B $(C@T7BGQ(B $(C9.@Z8&(B $(C;hA&GO4B5%4B(B, $(C8&(B $(C@T7BGU4O4Y(B. + $(C4B(B,$(CE0:85e?!<-(B "Delete"$(C6s0m(B $(C=a@V4B(B $(CE08&(B $(C4-7/<-(B $(C@T7BGU4O4Y(B. +"Delete" $(C4k=E?!(B"Rubout"$(C6s0m(B $(C=a@V@;(B $(CAv55(B $(C8p8(4O4Y(B. $(C:84Y(B $(C@O9]@{@87N(B, + $(C4B(B, $(CGv@gD?<-0!(B $(C@V4B(B $(C@'D!@G(B $(CAw@|@G(B $(C9.@Z8&(B $(C;hA&GU4O4Y(B. + + >> $(C9.@Z8&(B $(C8n03A$55(B $(CE8@LGAGO0m(B, $(C1W8.0m3*<-(B $(C1W0M@;(B $(C8&(B $(C;g(B + $(C?kGO?)(B $(C;hA&GO<> $(C?@8%BJ86Ax@;(B $(C3Q@;(B $(C6'1nAv(B $(CEX=:F.8&(B $(CE8@LGAGO<nA.3*?M(B + "$(C0hFAw(B $(C@L>nAv0m(B $(C@V4B(B $(C0M@;(B $(C3*E83;0m(B + $(C@V=@4O4Y(B. + + $(C@L0M@:(B, $(C1[7N(B $(C<38mGO4B(B $(C0M:84Y(B $(C=GA&7N(B $(CGX:84B(B $(CFm@L(B $(C@_(B $(C>K(B $(C> $(CA61]@|(B $(C@T7BGQ(B, $(C0hn0!557O(B $(CGX:8<> $(CD?<-8&(B $(CG`@G(B $(C<15N7N(B $(C@L5?GO0m(B, $(C8&(B $(C@T7BGO<U@G(B $(CG`0z(B + $(C@L>nA.(B $(C9v834O4Y(B. $(C@L>nAx(B $(CG`@L(B $(CH-8i@G(B $(CFx:84Y(B $(C1f0T(B $(C5G8i(B, $(C0h> $(C8&(B $(C4)8#0m(B, $(CGQ9x(B $(C4u(B $(CG`4\6tAv@=@;(B $(C;p@TGO<n4B(B, $(C9]:9(B $(CH8> C-u 8 * $(C6s0m(B $(C@T7BGO?)(B $(C:8<n6;0T(B $(C5G>z=@4O1n(B? + + $(C5N03@G(B $(CG`(B $(C;g@L?!(B $(C0x9iG`@;(B $(C885i0m(B $(C=M@:(B $(C0f?l?!4B(B, $(C5N9xB0(B $(CG`@G(B $(C<15N(B +$(C7N(B $(C0!<-(B, C-o $(C8&(B $(C@T7BGU4O4Y(B. + + >> $(C@{4gHw(B $(CG`@G(B $(C<15N?!(B $(C0!<-(B, $(C0E1b<-(B C-o $(C8&(B $(C@T7BGO?)(B $(C:8<z=@4O4Y(B. $(C9.@Z?M(B $(C00@L(B, $(C4\>n3*(B $(CG`55(B +$(C;hA&GR(B $(C`GO8i(B $(C4Y@=0z(B $(C00=@4O4Y(B. + + $(CD?<-Aw@|@G(B $(C9.@Z8&(B $(C;hA&(B + C-d $(CD?<-0!(B $(C@V4B(B $(C9.@Z8&(B $(C;hA&(B + + ESC $(CD?<-Aw@|@G(B $(C4\>n8&(B $(C;hA&(B + ESC d $(CD?<-@'D!(B $(C@LHD?!(B $(C@V4B(B $(C4\>n8&(B $(C;hA&(B + + C-k $(CD?<-@'D!7N:NEM(B $(CG`3!1nAv8&(B $(C;hA&(B + + $(C9+>y@N0!8&(B $(C;hA&GQ(B $(CHD?!(B, $(C1W0M@;(B $(C?x7!4k7N(B $(C5G598.0m(B $(C=M@;(B $(C6'0!(B $(C@V=@4O(B +$(C4Y(B. Emacs$(C4B(B, $(CGQ9.@Z:84Y(B $(CE+(B $(C4\@'7N(B $(C;hA&8&(B $(CG`GQ(B $(C6'?!4B(B, $(C;hA&GQ(B $(C3;?k@;(B +$(C:8A8GO?)(B $(C5S4O4Y(B. $(C?x7!4k7N(B $(C5G598.4B5%4B(B, C-y $(C8&(B $(C;g?kGU4O4Y(B. $(CAV@GGX>_(B +$(CGO4B(B $(C0M@:(B, C-y $(C8&(B $(C;hA&8&(B $(CG`GQ(B $(C@eF4O6s(B, $(C>n5p?!<-6s55(B $(CGR(B $(Cn@L9G7N(B, $(C@L0M@;(B $(C;g?kGO?)(B $(CEX=:F.8&(B $(C@L5?GR(B $(Cn?!4B(B, "Delete" $(C8m7I>n?M(B, "Kill" $(C8m7I>n0!(B $(C@V=@(B +$(C4O4Y(B. "Kill" $(C8m7I>n?!<-4B(B $(C;hA&5H(B $(C0M@:(B $(C:8A85GAv88(B, "Delete"$(C?!<-4B(B $(C:8A8(B +$(C5GAv(B $(C>J=@4O4Y(B. $(C4\(B, $(C9]:9H8nAv8i(B, $(C:8A85K4O4Y(B. + + >> C-n $(C@;(B 2$(CH8(B $(CA$55(B $(CE8@LGAGO0m(B, $(CH-8i@G(B $(C@{4gGQ(B $(C@e`(B, C-k $(C?!(B $(C9]:9H8(B $(C> C-y $(C8&(B $(C=CGhGO?)(B $(C:8<n(B $(C:8A85G(B +$(C0m(B, C-y$(C7N(B, $(C1W(B $(C@|:N0!(B $(C2t3;>nA}4O4Y(B. + + >> C-k $(C8&(B $(C8n9x(B $(CE8@LGAGO?)(B $(C:8<> $(CEX=:F.8&(B $(C2t3;4B5%4B(B, C-y $(C@T4O4Y(B. $(CD?<-8&(B $(C8nG`(B $(C9X@87N(B $(C@L5?=CE0(B + $(C0m(B, $(CGQ9x(B $(C4u(B C-y $(C8&(B $(CE8@LGAGO?)(B $(C:8<n62(B $(CEX=:F.0!(B $(C:8A85G>n(B $(C@V0m(B, $(C4u183*(B $(C4Y8%(B $(CEX=:F.8&(B $(C;hA&GO8i(B +$(C>n6;0T(B $(C5G0Z=@4O1n(B? C-y$(C4B(B, $(C0!@e(B $(CCV1Y(B $(C;hA&5H(B $(C0M@;(B $(C2tA}>n3@4O4Y(B. + + >> $(CG`@;(B $(C;hA&GO0m(B, $(CD?<-8&(B $(C@L5?=CE00m(B, $(C4Y8%(B $(CG`@;(B $(C;hA&GO<pA&6s55(B, $(CEX=:F.8&(B $(C:/0fGO?4Av88(B, $(C1W0M@;(B $(C?x7!4k7N(B $(C5G598.0m(B $(C=M@;(B $(C6'(B +$(C4B(B C-x u$(C7N(B $(C0mD(4O4Y(B. $(C:8Ek@:(B $(C@_8x5H(B $(C8m7I>n8&(B $(C9+H?7N(B $(CGO4B(B $(C@[5?@;(B $(CGU4O4Y(B. +$(C9]:9GX<-(B UNDO$(C8&(B $(CG`GO7A0m(B $(CGR(B $(C6'4B(B, $(C8n9x@L3*(B $(C1W(B $(C8m7I>n8&(B $(CG`GO8i(B $(C5G557O(B +$(C5G>n(B $(C@V=@4O4Y(B. + + >> $(C@L(B $(CG`@;(B C-k$(C7N(B $(CAv?l<n@T4O4Y(B. $(C1b4I@:(B, C-x u$(C?M(B $(C00(B + $(C=@4O4Y(B. + + C-_$(C3*(B C-x u$(C?!(B UNDO$(C@G(B $(CH8_(B $(CGU4O4Y(B. $(C:8A8GOAv(B $(C>J@88i(B, $(CG`GQ(B $(C:/0f@:(B, Emacs$(C8&(B $(CA>7aGO8i(B $(C5?=C?!(B $(C@R>n(B +$(C9v8.0T(B $(C5K4O4Y(B. + + $(CAv1](B $(C:80m(B $(C@V4B(B $(CH-@O?!(B $(C4kGX<-(B, $(C4g=E@L(B $(CFmA}@;(B $(CG`GQ(B $(C0M@;(B $(C=a3V=@4O4Y(B. +$(CAv1](B, $(C:80m(B $(C@V4B(B $(CH-@O@L6u(B $(C0M@:(B, $(C0#4\Hw(B $(C8;GO8i(B $(CFmA}GO0m(B $(C@V4B(B $(CH-@O(B $(C@ZC<@T(B +$(C4O4Y(B. + + $(C4g=E@L(B $(CH-@O@;(B $(C<<@L:j(B($(C:8A8GQ4Y(B)$(CGO1b(B $(C1nAv(B, $(CAv1]1nAv@G(B $(C:/0f@:(B $(CFmA}GO(B +$(C0m@V4B(B $(CH-@O?!(B $(C=a3V4B(B $(C0M@:(B $(C>F4U4O4Y(B. $(C1W0M@:(B, $(C4g=E@L(B $(C@L?M(B $(C00@L(B $(C:/0fGO0m(B +$(C=MAv(B $(C>J@:5%55(B, $(C55A_1nAv(B $(C:/0f@;(B $(C0!GQ(B $(C0M@L(B $(CA&8Z4k7N(B $(C=a3V>nAv4B(B $(C@O@L(B $(C>x55(B +$(C7O(B $(CGO1b(B $(C@'GX<-(B $(C@T4O4Y(B. + + $(C<<@L:j@;(B $(CG`GQ(B $(C5ZA6Bw(B $(C:/0fGQ(B $(C0M@L(B $(C@_8x(B $(C5G>n(B $(C@V@;(B $(C6'8&(B $(C@'GO?)(B Emacs +$(C4B(B $(C@L8'@;(B $(C:/0fGO?)(B $(C?x:;(B $(CH-@O@;(B $(C321i4O4Y(B. + +$(C:q0m(B: $(C6GGQ(B, Emacs$(C4B(B $(C?9CxGR(B $(Cx4B(B $(C;sEB?!(B $(C4k:qGO?)(B, $(C@OA$GQ(B $(C=C(B + $(C0#0#0]@87N(B $(C@Z5?@{@87N(B $(CFmA}GO0m(B $(C@V4B(B $(CH-@O@G(B $(C3;?k@;(B $(C@L8'(B + $(C@;(B $(C:/0fGQ(B $(CH-@O?!(B $(C<<@L:jGU4O4Y(B. $(C@L0M?!(B $(C@GGX(B, $(C88@O@G(B $(C0f?l(B + $(C4B(B $(CG`GQ(B $(C:/0f?!(B $(C4kGO?)(B $(CCVF7!(B $(CBJ@;(B $(C:88i(B, $(C@L?M(B $(C00@:(B $(C6f@87N(B $(C8p5e6s@N@L(B $(CG%=C5G>n(B $(C@V4Y(B +$(C0m(B $(C;}0"GU4O4Y(B. + +($(C?9(B) [--]J:--**-Mule: MULE.tut (Fundamental) ---55%-------------- + + + $(C@L(B Emacs$(CF)Ed8.>s@G(B $(C:9;g:;@:(B MULE.tut$(C@L6s0m(B $(C:R8.0m(B $(C@V=@4O4Y(B. $(CH-@O(B +$(C@;(B $(CH-@N5e(B($(CH-@O@;(B $(CC#>F<-(B $(C9vF[?!(B $(C@P>n3V4B(B $(C0M(B)$(CGO8i(B, MULE.tut$(C@G(B $(C:N:P?!(B $(CG%=C(B +$(C5K4O4Y(B. $(C?98&(B $(C5i8i(B, new-file$(C@L6s4B(B $(C@L8'@G(B $(CH-@O@;(B $(CH-@N5eGO?44Y8i(B, "Mule: +new-file"$(C@L6s4B(B $(C8p5e6s@N@L(B $(C5G0ZAv?d(B. + +$(CAV@G(B: $(C8p5e6s@N?!(B $(C4kGX<-4B(B $(C3*A_?!(B $(C<38mGO0Z=@4O4Y(B. $(C@a1q(B $(C1b4Y8.=C(B + $(C1b8&(B. + + $(CH-@O@;(B $(CH-@N5eGO0E3*(B, $(C<<@L:jGO4B(B $(C8m7I>n4B(B, $(CAv1]1nAv@G(B $(C0M0z4B(B $(C4^8.(B, +2$(C03@G(B $(C9.@Z7N(B $(C5G>n(B $(C@V=@4O4Y(B. C-x $(C?!(B $(C@L>n<-(B $(C@T7BGO4B(B $(C9.@Z0!(B, $(CH-@O?!(B $(C4kGX(B +$(C<-(B $(CG`GO4B(B $(CA6@[@;(B $(C3*E83@4O4Y(B. + + $(CGQ0!Av(B $(C4u(B, $(CAv1]1nAv@G(B $(C0M0z(B $(C4Y8%(B $(CA!@:(B, $(CH-@N5e(B $(C=C(B, $(CH-@O8m@;(B Emacs$(C0!(B +$(C90>n:>4O4Y(B. $(C@L0M@;(B, $(C4\8;7N:NEM(B $(C@Nn5i?)?@4B(B $(C8m7I>n6s0m(B $(C8;GO0m(B +$(C@V=@4O4Y(B. + + +$(CAV@G(B: $(C@L(B $(C0f?l4B(B $(CH-@O8m(B $(C@T4O4Y(B. + + C-x C-f $(CH-@O@;(B $(CC#4B4Y(B($(CH-@N5eGQ4Y(B) + + Emacs$(C4B(B $(CH-@O8m@;(B $(C90>n?I4O4Y(B. $(C@L0M@:(B, $(CH-8i9X@G(B $(CG`?!(B $(C3*E8334O4Y(B. +$(CH-@O8m@;(B $(CAvA$GO0m(B $(C@V4B(B $(C:N:P@:(B, $(C9L4O9vF[6s0m(B $(C:R8.?l4B(B $(C0M@T4O4Y(B. $(C9L4O9v(B +$(CF[4B(B $(C@L?M(B $(C00@L(B $(C;g?k5K4O4Y(B. $(CH-@O8m?!(B $(C@L>n<-(B, $(C8.4xE08&(B $(C4)8#8i(B, $(C9L4O9vF[(B +$(C?!(B $(CG%=C5G>nAx(B $(C3;?k@:(B $(C4u(B $(CGJ?dGOAv(B $(C>J1b(B $(C6'9.?!(B $(CAv?vA.(B $(C9v834O4Y(B. + + >> C-x C-f$(C6s0m(B $(CE8@LGAGQ(B $(C5Z?!(B C-g$(C6s0m(B $(CE8@LGAGO<n55(B $(CCkn62(B $(CH-@O55(B $(CC#Av(B $(C>J=@4O4Y(B. + + $(C@L9x?!4B(B $(CH-@O@;(B $(C<<@L:jGO?)(B $(C:8<n8&(B $(C;g?kGU4O4Y(B. + + C-x C-s $(CH-@O@;(B $(C<<@L:jGQ4Y(B + + Emacs$(C@G(B $(C3;?k@:(B $(CH-@O?!(B $(C=a3;>nA}4O4Y(B. $(C<<@L:jGR(B $(C6'(B, $(C?x:;@G(B $(CH-@O@:(B $(C;u(B +$(C7N?n(B $(C@L8'@;(B $(C:Y?)<-(B $(C320\Av1b(B $(C@V@89G7N(B $(C3;?k@:(B $(C>x>nAvAv(B $(C>J=@4O4Y(B. $(C@L(B $(C;u(B +$(C7N?n(B $(C@L8'@:(B $(C?x:;@G(B $(CH-@O@G(B $(C@L8'?!(B '~'$(C8&(B $(C:Y@N(B $(C0M@T4O4Y(B. + + $(C%;<<@L:j0!(B $(C3!3*8i(B, Emacs$(C4B(B $(C<<@L:jGQ(B $(CH-@O@G(B $(C@L8'@;(B $(CG%=CGU4O4Y(B. + + >> C-x C-s$(C6s0m(B $(CE8@LGAGO0m(B $(CF)Ed8.>s@G(B $(C:9;g:;@;(B $(C<<@L:jGO<`(B, 2$(C9xB0@G(B $(CH-@O@;(B C-x C-f $(C7N(B $(C2(3;8i(B, 1$(C9xB0@G(B $(CH-@O@:(B Emacs$(C3;:N(B +$(C?!(B $(C32=@4O4Y(B. Emacs$(C3;:N?!(B $(C@V4B(B $(CH-@O7N:NEM(B $(CEX=:F.8&(B $(C@P>n3V>n(B $(C:8A8GO0m@V(B +$(C4B(B $(C0M@:(B $(C9vF[6s0m(B $(C:R8.?s4O4Y(B. $(CH-@O@;(B $(C2(3;4B(B $(C0M@:(B, Emacs$(C3;:N?!(B $(C;u7N?n(B +$(C9vF[8&(B $(C885l4O4Y(B. + + Emacs $(C3;?!(B $(C:8A8GO0m(B $(C@V4B(B $(C9vF[@G(B $(C8.=:F.8&(B $(C:84B5%4B(B, $(C4Y@=0z(B $(C00@L(B +$(CE8@LGAGU4O4Y(B. + + C-x C-b + + >> C-x C-b $(C6s0m(B $(CE8@LGAGO<n60GQ(B $(C@L8'@;(B $(C0.(B + $(C0m(B $(C@V4B0!(B, $(C1W8.0m(B, $(C>n60GQ(B $(CH-@O8m@;(B $(C:Y@L0m(B $(C@V4B(B $(C0M@N0!(B $(C0|B{(B + $(CGO<J4B(B $(C0M55(B $(C@V=@4O4Y(B. $(C?98&(B $(C5i8i(B, "*Buffer +List*" $(C6s4B(B $(CH-@O@:(B $(C>x=@4O4Y(B. $(C@L0M@:(B C-x C-b $(C?!(B $(C@GGO?)(B $(C885i>nAx(B $(C9vF[8.(B +$(C=:F.?!(B $(C4kGQ(B $(C9vF[@T4O4Y(B. + + $(C4g=E@L(B $(C:80m(B $(C@V4B(B Emacs$(C@)55?l3;?!(B $(C@V4B(B, $(C>n60GQ(B $(CEX=:F.6s55(B, $(C>n4@0M(B +$(C@N0!@G(B $(C9vF[3;?!(B $(C@V=@4O4Y(B. + + >> $(C9vF[8.=:F.8&(B $(CAv?l1b(B $(C@'GX(B C-x 1 $(C6s0m(B $(CE8@LGAGO<`(B, $(C>n62(B $(CH-@O@G(B $(CEX=:F.?!(B $(C:/0f@;(B $(CG`GO0m3*<-(B, $(C4Y8%(B $(CH-@O@;(B $(C2(3;>z(B +$(C4Y0m(B $(CG_4Y8i(B, $(CCVCJ@G(B $(CH-@O@:(B $(C<<@L:j5G>n(B $(C@VAv(B $(C>J=@4O4Y(B. $(C1W(B $(C:/0f@:(B Emacs +$(C3;:N@G(B $(CH-@O0z(B $(C4k@@GO4B(B $(C9vF[(B $(C3;?!88(B $(CG`GO?)A.(B $(C@V=@4O4Y(B. + + 2$(C9xB0@G(B $(CH-@O?!(B $(C4k@@GO4B(B $(C9vF[8&(B $(C885i1b55GO0m(B, $(C?!5pF.GO4u6s55(B, 1$(C9x(B +$(CB0@G(B $(CH-@O?!(B $(C4k@@GO4B(B $(C9vF[?!4B(B $(C>F9+71(B $(C?5Gb@;(B $(CAVAv(B $(C>J=@4O4Y(B. $(C@L0M@:(B $(C4k(B +$(C4\Hw(B $(C;g?kGO1b(B $(C=10T(B, $(C6GGQ(B, 1$(C9xB0@G(B $(CH-@O?!(B $(C4k@@GO4B(B $(C9vF[8&(B $(CH.:8GO?)(B $(C5N(B +$(C1b(B $(C@'GO?)(B $(C55?r@L(B $(C5G4B(B $(C9f9}@T4O4Y(B. + + C-x C-s $(C7N(B $(C9vF[8&(B $(C<<@L:jGO1b(B $(C@'GO?)(B C-x C-f $(C7N(B $(C9vF[8&(B $(C13CF7!@G(B $(C8m7I>n8&(B $(C;g?kGU4O4Y(B. + + C-x s $(CGv@g(B $(C@V4B(B $(C9vF[8&(B $(C<<@L:jGQ4Y(B. + + C-x s $(C4B(B $(C3;?k@;(B $(C9Y2[(B $(C9vF[(B $(C@|C<8&(B $(CH-@O?!(B $(C<<@L:jGU4O4Y(B. $(C@L(B $(C6'(B, $(CGO3*(B +$(CGO3*@G(B ($(C<<@L:j5G>n>_(B $(CGR(B)$(C9vF[?!(B $(C4kGO?)(B, $(C<<@L:jGO4B0!(B, $(CGOAv(B $(C>J4B0!8&(B y$(C3*(B +n$(C@87N(B $(C9/=@4O4Y(B. $(C@L(B $(CG%=C4B(B $(CH-8i(B $(C9X@G(B $(CG`?!(B $(CG%=C5K4O4Y(B. $(C?98&(B $(C5i8i(B, $(C>F7!?M(B +$(C00=@4O4Y(B. + + Save file /usr/private/yours/MULE.tut? (y or n) + + + +$(C8m7I>n@G(B $(CH.@e(B +============= + + $(C?!5pEM?!4B(B, $(CD\F.7Q(B*$(CE03*(B $(C8^EM(B*$(CE07N(B $(C@T7BGR(B $(C@(B +$(C89@:(B $(C8m7I>n0!(B $(C@V=@4O4Y(B. $(C@L0M5i@;(B $(C4Y7g1b(B $(C@'GO?)(B, $(CH.@e(B(eXtend) $(C8m7I>n8&(B +$(C;g?kGU4O4Y(B. $(C@L0M?!4B(B, $(C>F7!@G(B 2$(C0!Av(B $(CA>7y0!(B $(C@V=@4O4Y(B. + + C-x $(C9.@Z?!(B $(C@GGQ(B $(CH.@e(B. $(C@L>n<-(B $(CGQ9.@Z8&(B $(C@T7BGU4O4Y(B. + ESC x $(C@L8'?!(B $(C@GGQ(B $(CH.@e(B. $(C@L>n<-(B $(C8m7I>n@G(B $(C@L8'@;(B $(C@T7BGU4O4Y(B. + + $(C@L0M5i@:(B $(C@O9]@{@87N(B, $(CFm8.GOAv88(B, $(CAv1]1nAv(B $(C:8>F?B(B $(C0M0z(B $(CA61](B $(C:s9xGO(B +$(C0T4B(B $(C;g?k5GAv(B $(C>J4B(B $(C8m7I>n8&(B $(C@'GQ(B $(C0M@T4O4Y(B. C-x C-f ($(CH-@N5e(B)$(C3*(B C-x C-s +($(C<<@L:j(B)$(C4B(B $(C@L(B $(C:N7y@T4O4Y(B. $(C@L?\?!(B, C-x C-c($(C?!5pEM@G(B $(CA>7a(B)$(C55(B $(C1W78=@4O4Y(B. + + C-z$(C4B(B Emacs$(C?!<-(B $(C:|A.3*?@4@5%?!(B $(C@ZAV(B $(C;g?k5G4B(B $(C9f9}@T4O4Y(B. Emacs$(C8&(B +$(CA>7aGO4B(B $(C0M@L(B $(C>F4O6s(B, $(C@O4\(B, csh$(C@G(B $(C79:'?!(B $(C5G59>F0!4B5%?!4B(B $(CA&@O(B $(CAA@:(B $(C9f(B +$(C9}@L6s0m(B $(C8;GR(B $(CF4U4O4Y(B. + +$(CAV@G(B: $(C4\(B, X-window$(C?!<-(B $(CG`GO0m(B $(C@V4B(B $(C0f?l(B, $(CH$@:(B $(C;g?kGO0m(B $(C@V4B(B + $(C=)@L(B sh$(C@O(B $(C6'4B(B, $(C1W78Av(B $(C>J=@4O4Y(B. + + C-x $(C8m7I>n4B(B,$(C89@L(B $(C@V=@4O4Y(B. $(C@L9L(B $(C9h?n(B $(C0M@:(B $(C>F7!@G(B $(C0M@T4O4Y(B. + + C-x C-f $(CH-@O@G(B $(CFmA}(B(Find) + C-x C-s $(CH-@O@G(B $(C:8A8(B(Save) + C-x C-b $(C9vF[8.=:F.@G(B $(CG%=C(B + C-x C-c $(C?!F7aGQ4Y(B. $(CH-@O@G(B $(C:8A8@:(B, $(C@Z5?@{@87N4B(B $(CG`GO?)(B + $(CAvAv(B $(C>J4B4Y(B. $(C1W7/3*(B, $(CH-@O@L(B $(C:/0f5G>n(B $(C@V@88i(B, $(CH-@O@G(B $(C:8(B + $(CA8@;(B $(CGO4B0!(B, $(C>F4Q0!8&(B $(C90>n?I4O4Y(B. $(C:8A8GO?)(B $(CA>7aGO4B(B $(C:8(B + $(CEk@G(B $(C9f9}(B, C-x C-s C-x C-c $(C7N(B $(CGO4B(B $(C0M@T4O4Y(B. + + $(C@L8'?!(B $(C@GGQ(B $(CH.@e8m7I>n?!4B(B, $(C1W4YAv(B $(C;g?k5GAv(B $(C>J4B(B $(C0M@L3*(B, $(CF/A$@G(B +$(C8p5e?!<-9[?!(B $(C;g?k5GAv(B $(C>J4B(B $(C0M5n@L(B $(C@V=@4O4Y(B. $(C?97N<-(B, "command-apropos" +$(C8&(B $(C5l4O4Y(B. $(C@L(B $(C8m7I>n4B(B $(CE0?v5e8&(B $(C@T7B=CE00m(B, $(C1W0M?!(B $(C8ED!GO4B(B $(C8p5g(B $(C8m7I(B +$(C>n@G(B $(C@L8'@;(B $(CG%=CGU4O4Y(B. ESC x $(C6s0m(B $(CE8@LGAGO8i(B, $(C=:E)80(B $(C9X?!(B "M-x" $(C0!(B $(CG%(B +$(C=C5K4O4Y(B. $(C@L0M?!(B $(C4kGO?)(B, $(C=GG`GO4B(B $(C8m7I>n@G(B $(C@L8'(B($(CAv1]@G(B $(C0f?l(B, +"command-apropos")$(C8&(B $(C@T7BGU4O4Y(B. "command-a" $(C1nAv(B $(C@T7BGQ(B $(C5Z(B $(C=:Fd@L=:(B +$(C8&(B $(CD!8i(B, $(C5Z@G(B $(C:N:P@:(B $(C@Z5?@{@87N(B $(C8^?vA}4O4Y(B. $(C@L(B $(CHD(B, $(CE0?v5e8&(B $(C90@89G7N(B, +$(C>K0m(B $(C=M@:(B $(C9.@Z?-@;(B $(CE8@LGAGU4O4Y(B. $(C6GGQ(B, $(CE0?v5e8&(B $(C@T7BGOAv(B $(C>J@88i(B, $(C8p5g(B +$(C8m7I>n0!(B $(CG%=C5K4O4Y(B. + + >> ESC x $(C8&(B $(CE8@LGAGO0m(B, $(C@L>n<-(B, "command-apropos" $(CH$@:(B + "command-a" $(C@L6s0m(B $(CE8@LGAGU4O4Y(B. $(C4Y@=?!(B, + "kanji"$(C@L6s0m(B $(CE8@LGAGU4O4Y(B. + + $(C3*E83-(B "$(C@)55?l(B"$(C8&(B $(CAv?l4B5%4B(B, C-x 1 $(C@L6s0m(B $(CE8@LGAGU4O4Y(B. + +$(C8p5e6s@N(B +======== + + $(C88>`(B $(CC5C5Hw(B $(C8m7I>n8&(B $(CCF4Y8i(B, $(CH-8i@G(B $(C9XBJ@G(B $(C?!DZ?!8.>n6s0m(B $(C:R8.4B(B +$(C@en4B(B $(CH-8i@G(B $(CA&@O(B $(C9X(B $(CG`@T4O4Y(B. $(C1W(B +$(C9Y7N(B $(C@'@G(B $(CG`@:(B, $(C8p5e6s@N@L6s0m(B $(C:R8.0m(B $(C@V=@4O4Y(B. $(C8p5e6s@N@:(B $(C@L7/GQ(B $(C=D@8(B +$(C7N(B $(CG%=C5G>n(B $(C@V0ZAv?d(B. + + [--]J:--**-Mule: MULE.tut (Fundamental) ---NN%-------------- + + +$(CAV@G(B: NN%$(C@G(B NN$(C@:(B $(C<}@Z0!(B $(C5i>n(B $(C@V=@4O4Y(B. $(C4g=E@L(B $(C;g?kGO0m(B $(C@V4B(B + Emacs$(C@G(B $(C8p5e6s@N0z(B $(C4Y8&(B $(CAv55(B $(C8p8#Av88(B, $(C4gH2GOAv(B $(C8;557O(B. + $(C?98&(B $(C5i8i(B, $(C=C0#@L3*(B uptime$(C@L(B $(CG%=C5G0m(B $(C@V4B(B $(C0M@:(B, + display-time$(C@L6s4B(B $(C1b4I@L(B $(C@[5?GO0m(B $(C@V1b(B $(C6'9.@T4O4Y(B. + + $(C@L(B $(CG`?!(B $(C@GGO?)(B $(C89@:(B $(C@/?kGQ(B $(CA$:80!(B $(C>r>nA}4O4Y(B. + + + $(CAv1](B, $(C4g=E@L(B $(C:80m(B $(C@V4B(B $(CH-@O8m@;(B $(CG%=CGO0m(B $(C@V=@4O4Y(B. NN%$(C@:(B $(CGv@g(B $(C=:(B +$(CE)80@'?!(B $(CH-@O@G(B $(CA&@O(B $(C@'?!<-:NEM(B $(C8n(B $(CF[<>F.B00!(B $(CG%=C5G0m(B $(C@V4B(B $(C0!8&(B $(C3*E8(B +$(C3;0m(B $(C@V=@4O4Y(B. $(CH-@O@G(B $(C0!@e(B $(CCVCJ8&(B $(CG%=CGO0m(B $(C@V@88i(B, --Top--$(C6s0m(B $(CG%=C5K(B +$(C4O4Y(B. $(CH-@O@G(B $(C0!@e(B $(CCVHD8&(B $(CG%=CGO0m(B $(C@V4Y8i(B, --Bot--$(C6s0m(B $(CG%=C5K4O4Y(B. $(CH-8i(B +$(C3;?!(B $(CH-@O(B $(C@|:N0!(B $(CG%=C5G0m(B $(C@V4Y8i(B, --All--$(C6s0m(B $(CG%=C5K4O4Y(B. + + $(C8p5e6s@N@G(B $(Cn60GQ(B $(C8p5e?!(B $(C5i>n@V4B(B $(C0!8&(B $(C3*E8(B +$(C3;0m(B $(C@V=@4O4Y(B. $(CGv@g4B(B, $(C5pFzF.@N(B Fundamental$(C?!(B $(C5i>n0!(B $(C@V=@4O4Y(B. $(C@L0M55(B +$(C8^@LA.8p5e@G(B $(CGO3*@G(B $(C?9@T4O4Y(B. + + Emacs$(C4B(B Lisp mode$(C3*(B Text mode$(C?M(B $(C00@L(B, $(C4Y8%(B $(CGA7N1W7%>p>n3*(B $(CEX=:F.(B +$(C?!(B $(C4kGO?)(B $(C?!5pF.8&(B $(CG`GO1b(B $(C@'GQ(B $(C8n0!Av@G(B $(C8^@LA.8p5e8&(B $(C0.0m(B $(C@V=@4O4Y(B. +$(C>n62(B $(C6'6s55(B $(C9]5e=C(B $(C>n4@0M@N0!@G(B $(C8^@LA.8p5e@G(B $(C;sEB7N(B $(C5G>n(B $(C@V=@4O4Y(B. + + $(C0"0"@G(B $(C8^@LA.8p5e4B(B $(C8n0!Av@G(B $(C8m7I>n8&(B $(C@|Gt(B $(C4Y8%(B $(CG`5?@87N(B $(CGO?)(B $(C9v(B +$(C834O4Y(B. $(C?98&(B $(C5i>n(B $(C:8=J4O4Y(B. $(CGA7N1W7%(B $(C3;?!(B $(C8m7I>n8&(B $(C885e4B(B $(C8m7I>n0!(B $(C@V(B +$(C=@4O4Y(B. $(C8m7I>n8&(B $(C>n60GQ(B $(CG|=D@87N(B $(CGO4B0!4B(B, $(C0"(B $(CGA7N1W7%>p>n?!(B $(C5{6s<-(B +$(C4Y8#Av88(B, $(C0"0"@G(B $(C8^@LA.8p5e4B(B, $(C9]5e=C(B $(C3V>nA]4O4Y(B. + + $(C0"0"@G(B $(C8^@LA.8p5e?!(B $(C5i>n0!1b(B $(C@'GQ(B $(C8m7I>n4B(B $(C8p5e8m@L(B $(CH.@e5H(B $(C0M@87N(B +$(C5G>n(B $(C@V=@4O4Y(B. $(C?98&(B $(C5i8i(B, M-x fundamental-mode$(C4B(B Fundamental$(C7N(B $(C5i>n0!(B +$(C1b(B $(C@'GQ(B $(C0M@T4O4Y(B. + + $(C88>`(B, $(C?5>n8&(B $(C?!5pF.GQ4Y8i(B, Text mode$(C7N(B $(C5i>n0)4O4Y(B. + + >> M-x text-mode $(C6s0m(B $(CE8@LGAGO<> C-h m $(C8&(B $(C;g?kGO?)(B Text mode$(C?M(B Fundamental mode$(C@G(B $(CBw@L8&(B $(C>K>F(B + $(C:8<> C-x 1$(C7N(B $(C55E%8UF.8&(B $(CH-8i@87N:NEM(B $(CAv?l<n(B $(C>KFD:*@;(B $(C1W4k7N(B $(C@T7BGR(B $(Cs@;(B $(C:8<n(B $(C@V=@4O4Y(B. Mule $(C@:(B, $(CH-@O@TCb7B(B, $(C@T7B(B, $(CH-8iCb7B?!(B $(C4kGO?)(B, $(C0"(B +$(C0"(B $(C5683@{@87N(B $(CDZ5eC<0h8&(B $(CAvA$=CE3(B $(C> $(C8p5e6s@N(B $(C@'?!(B "J:","S:", $(CH$@:(B "E:"$(C0!(B $(CG%=C5G>n(B $(C@V4B0!(B $(CH.@N(B + $(CGO<n(B $(C@L?\(B +$(C@G(B $(C9.@Z(B($(C@O:;>n(B, $(CGQ19>n5n(B)$(C55(B $(CG%=CGQ4Y4B(B $(C0M@;(B $(C3*E83;0m(B $(C@V=@4O4Y(B. J$(C4B(B +JUNET$(C@87N(B $(C;g?k5G0m(B $(C@V4B(B JIS $(CDZ5e(B, S $(C4B(B Shift-JIS, E $(C4B(B $(C@O:;>n(BEUC $(C8&(B $(C3*(B +$(CE83;0m(B $(C@V=@4O4Y(B. $(C4Y19>n(B $(CG%=C@G(B $(C@/9+4B(B C-x C-k t $(C7N(B ON/OFF$(C@G(B $(CEd1[@L(B $(C0!(B +$(C4IGU4O4Y(B. + + $(C4Y@=@G(B $(C?94B(B, $(C@O4\(B $(C4Y19>nG%=C8&(B OFF$(CGO0m3*<-(B, $(C4Y=C(B $(CGQ9x(B ON$(C@;(B $(CG`GO?)(B +$(C:>4O4Y(B. + + >> C-x C-k t$(C8&(B 2$(C9x(B $(CG`GO<n(B $(C@V@;(B $(C6'(B, $(C88>`(B $(C4g=E@L(B $(C;g?kGO0m(B $(C@V(B +$(C4B(B $(C4\8;?!(B $(C8^EM(B*$(CE00!(B $(C:Y>n(B $(C@V@88i(B, $(C@L=:DI@LGA(B*$(CE0(B $(C4k=E?!(B $(C1W0M@;(B $(C;g?kGO4B(B +$(C0M@L(B $(C0!4IGU4O4Y(B. $(C@L(B $(C6'(B, $(C8^EM(B*$(CE0@G(B $(C;g?k9f9}@:(B $(CD\F.7Q(B*$(CE0?M(B $(C00@L(B $(C4)8#8i<-(B +$(C9.@Z8&(B $(CE8@LGAGU4O4Y(B. ESC <$(C9.@Z(B>$(C55(B M-<$(C9.@Z(B>$(C55(B $(C00@:(B $(C@[5?@;(B $(CGU4O4Y(B. $(CAv1](B +$(C1nAv@G(B $(C<38m?!<-(B ESC <$(C9.@Z(B>$(C6s0m(B $(CG`GO0m(B $(C@V4x(B $(C0w@L(B, M-<$(C9.@Z(B>$(C7N(B $(C5K4O4Y(B. $(CAV(B +$(C@GGX>_(B $(CGO4B(B $(C0M@:(B, $(C=,GAF.(BJIS$(C3*(B EUC$(CDZ5e(B $(C6'4B(B $(C;g?kGR(B $(Cx=@4O4Y(B. + + $(CDZ5eC<0h@G(B $(C13C<4B(B, $(C0"0"@G(B $(C9vF[?!(B $(C4kGX<-88(B $(C@/H?GU4O4Y(B. $(C0"0"@G(B, $(CDZ(B +$(C5eC<0h(B $(CAvA$?!(B $(C4kGX<-4B(B, C-h a coding-system $(C@87N:<(B $(C> C-h a coding-system $(C@87N(B $(C3*?@4B(B $(C55E%8UF.(B $(C3;@G(B, + set-display-coding-system, set-file-coding-system, + set-process-coding-system $(C@G(B $(C<38m@;(B $(C@P>n:8<n4B(B, $(CD?<-@'D!(B $(C@LHD8&(B $(C0K;vGQ4Y8i(B, C-s, $(CD?<-@'D!(B $(C@L@|@L(B +$(C6s8i(B C-r $(C@T4O4Y(B. C-s $(C8&(B $(CE8@LGAGO8i(B, $(C?!DZ?!8.>n?!(B "I-search:"$(C6s4B(B $(C9.@Z?-(B +$(C@L(B $(CGA7RF.7N<-(B $(CG%=C5K4O4Y(B. ESC$(C8&(B $(C4)8#8i(B, $(CA>7a5K4O4Y(B. + + + >> C-s$(C7N(B $(C0K;v@L(B $(C=C@[5K4O4Y(B. $(C1W8.0m(B, $(CC5C5Hw(B 1$(C9.@Z>?(B "cursor"$(C6s4B(B + $(C4\>n8&(B $(C@T7BGU4O4Y(B. 1$(C9.@Z(B $(C@T7BGR(B $(C6'864Y(B, $(CD?<-4B(B, $(C>n6;0T(B $(C?rAw(B + $(C@T4O1n(B? + + >> $(CGQ9x(B $(C4u(B C-s $(C8&(B $(CE8@LGAGO8i(B, $(C4Y@=@G(B "cursor"$(C8&(B $(CC#@;(B $(C> $(C8&(B 4$(CH8(B $(C@T7BGO0m(B, $(CD?<-@G(B $(C?rAw@S@;(B $(C:8<> ESC$(C8&(B $(C4)8#0m(B, $(CA>7aGU4O4Y(B. + + $(CC#0m(B $(C=M@:(B $(C9.@Z?-@;(B $(CE8@LGAA_?!55(B, $(CE8@LGAGQ(B $(C9.@Z:N:P88@87N(B, $(C0K;v@;(B +$(C=C@[GU4O4Y(B. $(C4Y@=(B $(C9.@Z8&(B $(CC#4B5%4B(B, $(C4Y=C(B C-s$(C8&(B $(CE8@LGAGU4O4Y(B. $(C88>`(B, $(C9.@Z(B +$(C?-@L(B $(CA8@gGOAv(B $(C>J@88i(B, $(C8^<7a5K4O4Y(B. + + $(C0K;v=GG`A_?!(B, $(C8&(B $(C@T7BGO8i(B, $(C0K;v9.@Z?-@G(B $(CA&@O(B $(C5Z@G(B $(C9.@Z0!(B +$(CAv?vA}4O4Y(B. $(C1W8.0m3*<-(B, $(CD?<-4B(B, $(C@L@|9x@G(B $(C@'D!7N(B $(C5G59>F0)4O4Y(B. $(C?98&(B $(C5i(B +$(C8i(B, "cu"$(C6s0m(B $(CE8@LGAGO0m(B, $(CCVCJ@G(B "cu"$(C@G(B $(C@'D!?!(B $(CD?<-0!(B $(C?rAw?44Y0m(B $(CGU=C4Y(B. +$(C?)1b?!<-(B $(C8&(B $(C@T7BGO8i(B, $(C<-D!6s@N@G(B 'u'$(C0!(B $(CAv?vAv0m(B, $(CD?<-4B(B 'u'$(C8&(B +$(CE8@LGAGO1b(B $(C@|?!(B, $(CD?<-0!(B $(C@V>z4x(B 'c'$(C@G(B $(C@'D!7N(B,$(C@L5?GU4O4Y(B. + + $(C0K;v=GG`A_?!(B, C-s $(C3*(B C-r $(C@L?\@G(B $(CD\F.7Q9.@Z8&(B $(CE8@LGAGO8i(B, $(C0K;v@:(B +$(CA>7aGU4O4Y(B. + + C-s $(C4B(B, $(CGv@g@G(B $(CD?<-@'D!(B $(C@LHD?!(B $(C3*?@4B(B $(C0K;v9.@Z?-@;(B $(CC#=@4O4Y(B. $(C88>`(B, +$(C@L@|(B $(CBJ@;(B $(CC#0m(B $(C=M@88i(B, C-r $(C@;(B $(CE8@LGAGO4B(B $(C0M@87N(B, $(C?*9fGb0K;v@L(B $(C0!4IGU4O(B +$(C4Y(B. C-s $(C?M(BC-r $(C4B(B, $(C0K;v@G(B $(C9fGb@L(B $(C9]4k@O(B $(C;S(B, $(C@|:N(B $(C00@:(B $(C?rAw@S@;(B $(CGU4O4Y(B. + +$(C8.D?=C:j(B $(C?!5pFC(B $(C79:'(B + + $(C6'6'7N(B, ($(C:;@G(B $(C>F4O0T(B) $(C8.D?=C:j(B $(C?!5pFC(B $(C79:'@L6s0m(B $(C:R8.4B(B $(C;sEB?!(B $(C5i(B +$(C>n0!4B(B $(C6'0!(B $(C@V=@4O4Y(B. $(C8^@LA.8p5e@G(B $(CJ=@4O4Y(B. + + $(C8.D?=C:j(B $(C?!5pFC(B $(C79:'7N:NEM(B $(C:|A.3*?@1b(B $(C@'GX<-4B(B, M-x top-level +$(C@L6s0m(B $(CE8@LGAGU4O4Y(B. + + >> $(C=CGhGO?)(B $(C:8<z4x(B $(C0M@T4O(B +$(C4Y(B. M-x top-level$(C@:(B, $(C>F9+71(B $(C?5Gb@;(B $(CAV0m(B $(C@VAv(B $(C>J=@4O4Y(B. + + $(C8.D?=C:j(B $(C?!5pFC(B $(C79:'7N:NEM(B $(C:|A.3*?@4B(B $(C0M?!(B $(C4kGX<-4B(B C-g$(C4B(B $(C5hAv(B $(C>J(B +$(C=@4O4Y(B. + + +$(CGoGA(B +==== + + Emacs$(C?!4B(B, $(C89@:(B $(C55?r1b4I@L(B $(C@V0m(B, $(C?)1b?!<-(B, $(C@|:N8&(B $(C<38mGO4B(B $(C0M@:(B +$(C:R0!4IGU4O4Y(B. $(C1W7/3*(B, $(C>FAw(B $(C8p8#4B(B $(C89@:(B $(C1b4I@;(B $(C9h?l1b(B $(C@'GX<-4B(B, +$(C6s0m(B $(C:R8.4B(B C-h $(C8&(B $(CE8@LGAGO4B(B $(C0M@87N(B, $(C89@:(B $(CA$:88&(B $(C@Tn<-(B $(CGJ?dGQ(B $(C?In62(B $(C?I`(B, C-h $(C8&(B $(CE8@LGAGO0m3*<-(B $(C86@=@L(B $(C:/G_4Y8i(B, C-g $(C8&(B $(CE8@LGAGO8i(B, +$(CCkn<-(B $(CE08&(B $(C@T7BGO8i(B, $(C1W(B +$(C8m7I>n?!(B $(C4kGQ(B $(CB*@:(B $(C<38m@;(B $(CG%=CGU4O4Y(B. + + >> C-h c C-p $(C6s0m(B $(CE8@LGAGO?)(B $(C:8<oGO0m(B $(C@VAv(B $(C>J@:(B $(C8m7I>n55(B $(C;}0"GX(B $(C3>(B $(Cn55(B C-h c $(C@G(B $(C5Z?!(B $(C@L>n(B +$(CA}4O4Y(B. + + $(C4u?m(B $(C;s<K0m(B $(C=M@88i(B, c $(C4k=E?!(B k $(C8&(B $(CAvA$GU4O4Y(B. + + >> C-h k C-p $(C6s0m(B $(CE8@LGAGO?)(B $(C:8<n@G(B $(C@L8'0z(B $(C1b4I@L(B $(CG%=C5K4O4Y(B. $(C4Y(B $(C@P>z@88i(B, +C-x 1 $(C6s0m(B $(CE8@LGAGO8i(B, $(C:|A.3*?I4O4Y(B. + + $(C@L?\?!55(B $(C55?r@L(B $(C5G4B(B $(C?I> C-h f previous-line $(C@;(B $(CE8@LGAGO0m(B, $(C@;(B $(C4)8#<n8&(B $(C=GG`GO4B(B $(CFcn8&(B $(CG%=CGU4O4Y(B. $(C@L(B $(C8m7I>n5i@:(B $(C8p5N(B ESC x $(C7N(B $(C=GG`GR(B + $(C> C-h a file $(C>K0m(B $(CE8@LGAGO0m(B, $(C@;(B $(C4)8#<n8&(B $(CG%=CGU4O4Y(B. $(C6GGQ(B, + find-file $(C@L3*(B write-file$(C6s4B(B $(C@L8'@G(B C-x C-f $(C3*(B C-x C-w $(C?M(B $(C00(B + $(C@:(B $(C8m7I>n55(B $(CG%=C5K4O4Y(B. + +$(C3!@87N(B +====== + +$(C@XAv8;0m(B: $(CA>7aGO4B5%4B(B, C-x C-c $(C6s0m(B $(CGU4O4Y(B. + + + $(C@L(B $(C@T9.Fm@:(B, $(CCJ=I@Z?!0T55(B $(C>K1b(B $(C=10T(B $(CGO557O(B $(C@G55GO0m(B $(C@V=@4O4Y(B. +$(C1W7/9G7N(B, $(CH$=C(B $(C9+>y@N0!(B $(C@LGXGO1b(B $(C>n7A?n(B $(CA!@L(B $(C@V4Y8i(B, $(CH%@Z<-(B $(CG*3d(B +$(CGOAv(B $(C8;0m(B, $(CF.A}@;(B $(C@b>F(B $(CAV<`(B, EMACS $(C8&(B $(C8n@OA$55(B $(C;g?kGO0m(B $(C:88i(B, $(C1W0M@;(B $(C1W885P4Y4B(B $(C0M@:(B +$(C8xGO0T(B $(C5I(B $(C0M@T4O4Y(B. $(CCVCJ?!4B(B $(C>n8.5U@}GR(B $(CAv55(B $(C8p8#0Z=@4O4Y(B. $(C1W7/3*(B, +$(C1W0M@:(B $(C>n60GQ(B $(C?!5pEM6s55(B $(C6H(B $(C00=@4O4Y(B. EMACS $(C?M(B $(C00@L(B, $(C4k4\Hw(B $(C89@:(B $(C0M@L(B +$(C0!4IGQ(B $(C0f?l?!4B(B $(CF/Hw(B $(C1W780ZAv?d(B. $(C1W8.0m(B, EMACS $(C?!<-4B(B, $(C=GA&7N(B, $(C9+>y@L(B +$(C3*(B $(CGR(B $(Cn(B MicroEMACS (kemacs) $(C@T9.Fm(B" +$(C@;(B GNUE- macs (Nemacs)$(C@G(B Tutorial$(C?k@87N(B $(C0mCD>4(B $(C0M@T4O4Y(B. + + Jonathan Payne $(C?!(B $(C@GGQ(B "JOVE Tutorial" (19 January 86) $(C@;(B $(C:/0fGQ(B + $(C0M@L0m(B, $(C1W0M@:(B $(C?x7!(B, CCA-UNIX$(C@G(B Steve Zimmerman $(C?!(B $(C@GGX<-(B $(C:/0f5H(B, + MIT $(C@G(B "Teach-Emacs" $(C@T9.Fm(B (31 October 85) $(C@;(B ($(C4u?m(B) $(C:/0fGQ(B $(C0M@L(B + $(C>z=@4O4Y(B. + + Update - February 1986 by Dana Hoggatt. + + Update - December 1986 by Kim Leburg. + + Update/Translate - July 1987 by SANETO Takanori + +$(CF/:0GQ(B $(C0(;g(B +=========== + + $(CCVCJ?!(B $(C@L(B $(C@O:;>n9x?*@;(B $(C@[<:GQ(B, SANETO Takanori$(C>>(B. $(C@L(B $(C9.@e@:(B GMW + +Wnn + Nemacs$(C@;(B $(C;g?kGO?)(B $(C@[<:G_=@4O4Y(B. $(C1W?M(B $(C00@:(B $(CHG8"GQ(B $(CGA7N1W7%@;(B $(C885g(B +$(C8p5g(B $(C:P?!0T(B $(C0(;g@G(B $(C6f@;(B $(CG%GO0m(B $(C=M=@4O4Y(B. $(C9x?*@L6s5g0!(B, $(C@T7B(B $(C5n(B +$(C?)7/8p7N(B $(C55?M(B $(CAX(B $(CHDAvGO6s>(B, $(C4k4\Hw(B $(C0(;gGU4O4Y(B. + + + +$(C?@?*(B, $(C0EA~(B, $(C@L(B $(C?\@G(B $(C9.C%@:(B $(C>F7!@G(B $(C;g6w?!0T(B $(C@V=@4O4Y(B. + + $BNkLZM5?.(B hironobu@sra.co.jp + + +Update/Add - December 1987 by Hironobu Suzuki +Update/Add - November 1989 by Ken'ichi Handa +Update/Add - January 1990 by Shigeki Yoshida +Update/Add - March 1992 by Kenichi HANDA + + +$(C6G4Y8%(B $(C0(;g(B +=========== + + $(C@L(B $(C9.<-4B(B "$(C@O:;>n(B GNUEMACS(Mule) $(C@T9.Fm(B"$(C@;(B $(CGQ19>n7N(B $(C9x?*GO?)(B, +hemacs$(C7N(B $(C@[<:GQ(B $(C0M@T4O4Y(B. $(C@O:;>n9x?*@;(B $(C4c4gGQ(B $(C8p5g(B $(C:P(B, hemacs$(C8&(B +$(C039_GO?)(B $(CAV=E(B $(C:P(B, $(CF/Hw(B Mule$(C0z(B hemacs$(C@G(B $(CH/0f18C`?!(B $(C89@:(B $(C55?r@;(B $(CAX(B +$(C136G4kGP(B $(C3*0!?@?,18=G(B $(CA9>w;}@N(B Masashi SHIMBO$(C>>?M(B Katsuyoshi +Yamagami$(C>>?!0T(B $(C0(;g@G(B $(C6f@;(B $(C@|GU4O4Y(B. + + 1993. 9. 25 + + $(C136G4kGP(B $(C0xGP:N(B $(C@|1b0xGP0z(B $(C3*0!?@?,18=G(B + Dosam HWANG hwang@forest.kuee.kyoto-u.ac.jp diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL.kr --- a/etc/TUTORIAL.kr Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,776 +0,0 @@ - ============================== - $(C@O:;>n(B GNUEMACS(Mule) $(C@T9.Fm(B - ============================== - -$(CAV@G(B: $(C@L(B $(C@T9.Fm@:(B, "$(C9h?l1b:84Y(B $(C@Mn(B - $(C@V=@4O4Y(B. ">>" $(C7N:NEM(B $(C=C@[GO4B(B $(CG`@:(B, $(C1W(B $(C6'(B $(C9+>y@;(B $(CGX>_(B - $(CGO4B0!8&(B $(CAv=CGO0m(B $(C@V=@4O4Y(B. - - Mule $(C@G(B $(C8m7I>n8&(B $(C@T7BGR(B $(C6'?!4B(B, $(C@O9]@{@87N(B $(CD\F.7Q(B*$(CE0(B($(CE0(B*$(CEi?!(B, -CTRL $(C6G4B(B, CTL $(C6s0m(B $(C=a@V4Y(B)$(C3*(B $(C8^E8(B*$(CE0(B($(C:8Ek(B, $(C@L=:DI@LGA(B*$(CE08&(B $(C;g?kGQ4Y(B)$(C0!(B -$(C;g?k5K4O4Y(B. $(C1W7!<-(B, CONTROL $(C@L6s5g0!(B META $(C6s0m(B $(C>24B(B $(C4k=E?!(B, $(C4Y@=0z00@:(B -$(C1bH#8&(B $(C;g?kGO4B(B $(C0M@87N(B $(CGU4O4Y(B. - -C-<$(C9.@Z(B> $(CD\F.7Q(B*$(CE08&(B $(C4)8%C$(B, <$(C9.@Z(B>$(CE08&(B $(C4)8(4O4Y(B. $(C?98&(B $(C5i8i(B, - C-f $(C4B(B, $(CD\F.7Q(B*$(CE08&(B $(C4)8#8i<-(B f $(CE08&(B $(C4)8#4B(B $(C0M@;(B - $(C@G9LGU4O4Y(B. -<> - >> $(C1W7/8i(B, C-v (View Next Screen; $(C4Y@=@G(B $(CH-8i@;(B $(C:;4Y(B) $(C8&(B $(CE8@LGA(B - $(CGO?)(B $(C:8< $(C@L=:DI@LGA(B*$(CE08&(B $(C4)8#0m3*<-(B, $(C1W(B $(C5Z(B <$(C9.@Z(B>$(CE08&(B $(C4)8(4O4Y(B. - -$(CAV@G(B: <$(C9.@Z(B>$(C4B(B, $(C4k9.@Z3*(B $(Cn7N<-4B(B $(C00@:(B $(C@G9L0!(B - $(C5K4O4Y(B. $(C8^E8E08&(B $(C;g?kGR(B $(C $(C4k=E?!(B M- - <$(C9.@Z(B> ($(C8^E8E08&(B $(C4)8%C$(B<$(C9.@Z(B>$(CE08&(B $(C4)8%4Y(B) $(C8&(B $(C;g?kGR(B $(C7a=CE00m(B $(C=M@;(B $(C6'4B(B, C-x C-c $(C8&(B $(CE8@LGAGU4O4Y(B. - Emacs$(C8&(B csh$(C7N:NEM(B $(C1b5?GO0m(B $(C@V4B(B $(C0f?l(B, $(C<-=:Ff5eGO4B(B($(C@O=C(B - $(C@{@87N(B $(CA_4\GQ4Y(B)$(CGR(B $(Cz@88i(B, C-v $(C8&(B $(C@T7BGO?)(B $(CAV<U@G(B $(CH-8i0z(B $(C4Y@=(B $(CH-8i?!4B(B, $(CG%=C5G4B(B $(C3;?k?!(B $(C8nG`@G(B $(C9.@L(B $(CA_:95G0m(B -$(C@V=@4O4Y(B. $(CG%=C5G0m(B $(C@V4B(B $(C3;?k@L(B $(C?,n(B $(C@V4B(B $(C0M@;(B $(C>K(B $(CK(B $(CGJ?d0!(B $(C@V=@4O4Y(B. C-v -$(C?!(B $(C@GGO?)(B $(C>U@87N(B $(CAxG`GO4B(B $(C0M@:(B $(C@L9L(B $(C>K>R=@4O4Y(B. $(C?x7!@G(B $(C@Z8.7N(B $(C5G59>F(B -$(C0!4B5%4B(B, ESC v $(C8&(B $(CE8@LGAGU4O4Y(B. - - >> ESC v $(C?M(B C-v $(C8&(B $(C;g?kGO?)(B, $(C@|HD7N(B $(C@L5?GO4B(B $(C0M@;(B $(C8n9x(B $(C=C55GO?)(B - $(C:8<`(B -==== - $(CH-@O@;(B $(CH-8i4\@'7N(B $(C:80m(B $(C0!4B5%4B(B, $(C4Y@=@G(B $(C8m7I>n8&(B $(C;g?kGU4O4Y(B. - - C-v $(C>U@87N(B $(CGQ(B $(CH-8i:P(B $(CAxG`GQ4Y(B - ESC v $(C5Z7N(B $(CGQ(B $(CH-8i:P(B $(C5G59>F0#4Y(B - C-l $(CH-8i@;(B $(C4Y=C>44Y(B. $(C@L(B $(C6'(B, $(C?x7!(B $(CD?<-0!(B $(C@V>z4x(B $(CG`@L(B - $(CH-8i@G(B $(CA_>S?!(B $(C?@557O(B $(CGQ4Y(B - - >> $(CAv1](B $(CD?<-0!(B $(C>n5p?!(B $(C@V4B0!(B, $(C1W(B $(C1YC3?!(B $(C>n62(B $(CEX=:F.0!(B $(C=aA.(B $(C@V4B(B - $(C0!8&(B $(C1b>oGO<n5p7N(B $(C@L5?GO?44B(B - $(C0!(B, $(C1W(B $(C1YC3@G(B $(CEX=:F.4B(B $(C>n6;0T(B $(C5G>z4B0!8&(B $(CA6;gGO?)(B $(C:8<n(B -====================== - - $(CH-8i4\@'@G(B $(C@L5?@:(B $(CGR(B $(Cz=@4O4Y(B. $(C@LA&4B(B, $(CH-8i(B $(C3;?!<-(B, $(CF/(B -$(CA$@G(B $(C@eU(B(forward)$(C5Z(B(backward)$(C7N(B -$(C@L5?GO4B(B $(C8m7I>n8&(B $(C;g?kGO4B(B $(C0M@T4O4Y(B. $(C@L5i@G(B $(C8m7I>n4B(B $(C0"0"(B, C-p, C-n, -C-f, C-b $(C?!(B $(CGR4g5G>n(B $(C@V0m(B, $(CGv@g@G(B $(C@en(B $(C@V@89G7N(B, $(C?\?l1b(B $(C=,?o(B $(C0M@T4O4Y(B. $(C@L5i@:(B, $(C1b:;@{@N(B $(CD?<-@L5?(B $(C8m7I>n@L0m(B -, $(C@ZAV(B $(C;g?kGO4B(B $(C0M@T4O4Y(B. - - >> C-n $(C@;(B $(C8nH8A$55(B $(CE8@LGAGO0m(B, ($(CAv1](B, $(C4g=E@L(B $(C@P0m(B $(C@V4B(B) $(C@L(B $(CG`1n(B - $(CAv(B $(CD?<-8&(B $(C@L5?=CE0<> C-f $(C8&(B $(C;g?kGO?)(B $(CG`@G(B $(CA_0#A$557N(B $(C@L5?GO0m(B, C-p $(C@87N(B $(C8nG`A$55(B - $(C@'7N(B $(C@L5?GO?)(B $(C:8<> $(CG`@G(B $(C<15N?!<-(B C-b $(C8&(B $(CE8@LGAGO?)(B $(C:8<n5p7N(B $(C@L5?GU(B - $(C4O1n(B? $(C4Y=C(B $(CA61](B $(C4u(B C-b $(C8&(B $(CE8@LGAGO0m(B, $(C@L9x@:(B C-f $(C7N(B $(CG`3!(B $(CBJ(B - $(C@87N(B $(C5G59>F0!<n6;0T(B $(C5K4O1n(B? - - - $(CH-8i@G(B $(C<15N3*(B $(C8;9L8&(B $(C3Q>n<-(B $(CD?<-8&(B $(C@L5?=CE07A0m(B $(CGO8i(B, $(C1W(B $(C9fGb?!(B -$(C@V4B(B $(CEX=:F.0!(B $(C@L5?GO?)(B $(C?@0m(B, $(CD?<-4B(B $(CGW;s(B $(CH-8i3;?!(B $(C@V557O(B $(C5K4O4Y(B. - - >> C-n $(C@;(B $(C;g?kGO?)(B, $(CD?<-8&(B $(CH-8i@G(B $(CGO4\:84Y(B $(C9X@87N(B $(C@L5?=CDQ(B $(C:8<<(B - $(C?d(B. $(C9+>y@L(B $(C@O>n334O1n(B? $(CD?<-@G(B $(C@'D!4B(B $(C>n6;0T(B $(C:/GO?4=@4O1n(B? - - $(CGQ9.@Z(B $(C4\@'@G(B $(C@L5?@87N4B(B $(C9x0E7S4Y0m(B $(C;}0"5G8i(B, $(C4\>n4\@'7N(B $(C@L5?GR(B -$(Cn:P(B $(C>U@87N(B $(CAxG`GO0m(B, ESC b $(C7N(B $(CGQ(B $(C4\>n:P(B -$(C@L@|@87N(B $(C5G59>F0)4O4Y(B. - -$(CAV@G(B: $(C@O:;>n?!(B $(C4kGX<-4B(B, $(C4\>n@G(B $(C2w4B(B $(C4\@'@;(B $(C@N=DGR(B $(Cx=@4O(B - $(C4Y88(B, $(C@G;g@{@N(B $(C9.@}@;(B $(C4\>n@G(B $(C2w4B(B $(C4\@'7N<-(B $(CGO0m(B $(C@V=@4O(B - $(C4Y(B. - - >> ESC f $(C3*(B ESC b $(C8&(B $(C8nH8A$55(B $(CE8@LGAGO?)(B $(C:8<$(C4B(B $(C9.<-0|0h@G(B $(CC38.?!(B $(C;g?k5G0m(B, $(CGQFm(B C-<$(C9.@Z(B>$(C4B(B $(C1W0M(B -$(C:84Y55(B $(C4u?m(B $(C1b:;@{@N(B $(C4k;s(B($(C9.@Z6s5g0!(B $(CG`@L6s5g0!(B)$(C?!(B $(C4kGQ(B $(CA6@[?!(B $(C;g?k5K(B -$(C4O4Y(B. - - C-a $(C?M(B C-e $(C55(B $(C>K0m(B $(C@V@88i(B $(CFm8.GQ(B $(C8m7I>n@T4O4Y(B. C-a $(C4B(B $(CD?<-8&(B $(CG`@G(B -$(C<15N7N(B $(C@L5?=CE00m(B, C-e $(C4B(B $(CG`@G(B $(C3!@87N(B $(C@L5?=CE54O4Y(B. - - >> C-a $(C8&(B 2$(CH8(B, $(C1W8.0m3*<-(B C-e $(C8&(B 2$(CH8(B $(C@T7BGO?)(B $(C:8<n8&(B 2$(CH8@L;s(B $(C9]:9GO4u6s55(B, $(CD?<-4B(B $(C1W(B $(C@L;s(B $(C@L5?GOAv(B $(C>J4B(B $(C0M(B - $(C?!(B $(CAV@G(B. - - $(C5N0!Av(B $(C4u(B, $(C0#4\GQ(B $(CD?<-(B $(C@L5?(B $(C8m7I>n0!(B $(C@V=@4O4Y(B. $(CH-@O@G(B $(C<15N7N(B $(C@L5?(B -$(CGO4B(B ESC < $(C?M(B, $(CH-@O@G(B $(C3!@87N(B $(C@L5?GO4B(B ESC > $(C@T4O4Y(B. - - $(CEX=:F.(B $(C3;?!<-(B, $(CD?<-0!(B $(CA8@gGO4B(B $(C@'D!8&(B "$(CFw@NF.(B"$(C6s0m(B $(C:N8(4O4Y(B. $(C9Y2Y(B -$(C>n(B $(C8;GO8i(B, $(CD?<-4B(B, $(CEX=:F.@G(B $(C>n5p?!(B $(C@V4B0!8&(B $(CH-8i@'?!(B $(C3*E83;0m(B $(C@V4B(B $(C0M(B -$(C@T4O4Y(B. - - $(C>F7!?!(B $(C4\`GU4O4Y(B. $(C@L(B $(CA_?!4B(B, $(C4\>n3*(B $(CG`(B -$(C4\@'7N@G(B $(C@L5?8m7I>n55(B $(CFwGT5G>n(B $(C@V=@4O4Y(B. - - C-f $(CGQ(B $(C9.@Z(B $(C>U@87N(B $(CAxG`GQ4Y(B - C-b $(CGQ(B $(C9.@Z(B $(C5Z7N(B $(C5G59>F0#4Y(B - - ESC f $(CGQ(B $(C4\>n(B $(C>U@87N(B $(CAxG`GQ4Y(B - ESC b $(CGQ(B $(C4\>n(B $(C5Z7N(B $(C5G59>F0#4Y(B - - C-n $(C4Y@=(B $(CG`@87N(B $(C@L5?(B - C-p $(C@L@|(B $(CG`@87N(B $(C@L5?(B - - ESC ] $(C4\6t@G(B $(C3!@87N(B $(C@L5?(B - ESC [ $(C4\6t@G(B $(C<15N7N(B $(C@L5?(B - - C-a $(CG`@G(B $(CCVCJ7N(B $(C@L5?(B - C-e $(CG`@G(B $(CCVHD7N(B $(C@L5?(B - - ESC < $(CH-@O@G(B $(CCVCJ7N(B $(C@L5?(B - ESC > $(CH-@O@G(B $(CCVHD7N(B $(C@L5?(B - - >> $(C0"0"@G(B $(C8m7I>n8&(B $(C=C55GO?)(B $(C:8<n4B(B, $(C0!@e(B $(C@ZAV(B - $(C;g?k5G4B(B $(C0M@T4O4Y(B. $(CCVHD@G(B $(C5N0!Av4B(B, $(C@L(B $(C@enAx(B $(C0w@8(B - $(C7N(B $(C@L5?GO1b(B $(C6'9.?!(B, C-v $(C3*(B ESC v $(C8&(B $(C;g?kGO?)(B $(C?)1b7N(B $(C5G59>F(B - $(C?@557O(B $(CGO<n?!4B(B, $(C9]:9H8n8&(B $(C@T7BGO1b(B $(C@|?!(B, C-u -$(C?!(B $(C@L>n<-(B $(C9]:9GO4B(B $(CH8U@87N(B $(C@L5?GU4O4Y(B. - - >> C-n $(CH$@:(B C-p $(C?!(B $(C@{4gGQ(B $(C@N> C-u 3 C-v $(C6s0m(B $(C@T7BGO?)(B $(C:8<F0!4B5%4B(B, C-u 3 ESC v $(C8&(B $(C;g?kGO8i(B $(C5K4O4Y(B. - -$(CA_Av8m7I>n(B -========== - - C-g $(C6s4B(B $(C8m7I>n@L8g(B, $(C@T7B@;(B $(CGJ?d7N(B $(CGO4B(B $(C0M0z(B $(C00@:(B $(C8m7I>n8&(B $(CA_AvGR(B -$(Cn8&(B $(CGQC"(B $(C@T7BGO0m(B $(C@V4B(B $(C55A_?!(B, $(C1W0M@;(B $(CA_AvGO0m(B $(C=M(B -$(C@88i(B, C-g $(C8&;g?kGO8i(B $(C5K4O4Y(B. - - >> C-u 100 $(C8&(B $(CE8@LGAGO?)(B $(C@N`(B, $(C@_8xGO?)(B ESC $(C8&(B $(C@T7BGX(B $(C9v7H@;(B $(C6'55(B, C-g $(C8&(B $(C@T7BGO(B - $(C8i(B $(CCkJ4B(B $(CA6@[@;(B $(CGX9v8.4B(B $(C@{@L(B $(C@V=@4O(B -$(C4Y(B. $(C?98&(B $(C5i8i(B, $(C8m7I>n0!(B $(CA$@G5G>n(B $(C@VAv(B $(C>J4B(B $(CD\F.7Q(B*$(CE08&(B $(C@T7BGX(B $(C9v80(B $(C6'(B -$(C?!4B(B, Emacs$(C4B(B $(C:'@;(B $(C?o8.0m(B, $(C1W8.0m(B, $(CH-8i@G(B $(CA&@O(B $(C9X?!(B, $(C9+>y@L(B $(C3*;&4B(B $(C0!(B -$(C8&(B $(CG%=CGU4O4Y(B. - - Emacs $(C9vA/?!(B $(C5{6s<-4B(B, $(C@L(B $(C@T9.Fm?!(B $(C>2?)A.(B $(C@V4B(B $(C0M@;(B $(C=GG`GR(B $(Cx(B -$(C4B(B $(C0f?l0!(B $(C@V@;(B $(Cn4@(B $(C0M@N0!(B $(C@L5?E08&(B $(C4)8#0m(B, $(C1W(B $(C4Y@=@G(B $(C:N:P@87N(B $(CAxG`GO?)(B $(CAV<n7N:NEM@G(B $(CCb7B@;(B $(CG%=CGO1b(B $(C@'GO(B -$(C?)(B $(C3*E83-(B $(C?):P@G(B $(C@)55?l8&(B $(CAv?l1b(B $(C@'GO?)(B, $(C4Y@=@G(B $(C8m7I>n8&(B $(C>K(B $(CGJ?d0!(B $(C@V=@(B -$(C4O4Y(B. - - C-x 1 $(C@)55?l8&(B 1$(C037N(B $(CGQ4Y(B. - - C-x 1 $(C4B(B, $(C4Y8%(B $(C@)55?l8&(B $(CAv?l0m(B, $(CD?<-0!(B $(C@V4B(B $(C@)55?l8&(B, $(CH-8i@|C<7N(B -$(CH.@eGU4O4Y(B. - - >> $(CD?<-8&(B $(C@L(B $(CG`?!(B $(C0.0m(B $(C?M<-(B, C-u 0 C-l $(C@L6s0m(B $(CE8@LGAGU4O4Y(B. - - >> C-h k C-f $(C6s0m(B $(CE8@LGAGO<n@G(B $(C55(B - $(CE%8UF.8&(B $(CG%=CGO1b(B $(C@'GO?)(B $(C3*E8320z(B $(C5?=C?!(B, $(C@L(B $(C@)55?l0!(B $(C>n6;0T(B - $(CAY>n5e4B0!(B $(C0|B{GO<> C-x 1$(C@L6s0m(B $(CE8@LGAGO0m(B, $(C55E%8UF.0!(B $(C3*E8354x(B $(C@)55?l8&(B $(CAv?l<<(B - $(C?d(B. - -$(C;p@T0z(B $(C;hA&(B -=========== - - $(CEX=:F.8&(B $(CE8@LGAGO0m(B $(C=M@88i(B, $(C4\ $(C@;(B $(CE8@LGAGU4O4Y(B. - - $(CAw@|?!(B $(C@T7BGQ(B $(C9.@Z8&(B $(C;hA&GO4B5%4B(B, $(C8&(B $(C@T7BGU4O4Y(B. - $(C4B(B,$(CE0:85e?!<-(B "Delete"$(C6s0m(B $(C=a@V4B(B $(CE08&(B $(C4-7/<-(B $(C@T7BGU4O4Y(B. -"Delete" $(C4k=E?!(B"Rubout"$(C6s0m(B $(C=a@V@;(B $(CAv55(B $(C8p8(4O4Y(B. $(C:84Y(B $(C@O9]@{@87N(B, - $(C4B(B, $(CGv@gD?<-0!(B $(C@V4B(B $(C@'D!@G(B $(CAw@|@G(B $(C9.@Z8&(B $(C;hA&GU4O4Y(B. - - >> $(C9.@Z8&(B $(C8n03A$55(B $(CE8@LGAGO0m(B, $(C1W8.0m3*<-(B $(C1W0M@;(B $(C8&(B $(C;g(B - $(C?kGO?)(B $(C;hA&GO<> $(C?@8%BJ86Ax@;(B $(C3Q@;(B $(C6'1nAv(B $(CEX=:F.8&(B $(CE8@LGAGO<nA.3*?M(B - "$(C0hFAw(B $(C@L>nAv0m(B $(C@V4B(B $(C0M@;(B $(C3*E83;0m(B - $(C@V=@4O4Y(B. - - $(C@L0M@:(B, $(C1[7N(B $(C<38mGO4B(B $(C0M:84Y(B $(C=GA&7N(B $(CGX:84B(B $(CFm@L(B $(C@_(B $(C>K(B $(C> $(CA61]@|(B $(C@T7BGQ(B, $(C0hn0!557O(B $(CGX:8<> $(CD?<-8&(B $(CG`@G(B $(C<15N7N(B $(C@L5?GO0m(B, $(C8&(B $(C@T7BGO<U@G(B $(CG`0z(B - $(C@L>nA.(B $(C9v834O4Y(B. $(C@L>nAx(B $(CG`@L(B $(CH-8i@G(B $(CFx:84Y(B $(C1f0T(B $(C5G8i(B, $(C0h> $(C8&(B $(C4)8#0m(B, $(CGQ9x(B $(C4u(B $(CG`4\6tAv@=@;(B $(C;p@TGO<n4B(B, $(C9]:9(B $(CH8> C-u 8 * $(C6s0m(B $(C@T7BGO?)(B $(C:8<n6;0T(B $(C5G>z=@4O1n(B? - - $(C5N03@G(B $(CG`(B $(C;g@L?!(B $(C0x9iG`@;(B $(C885i0m(B $(C=M@:(B $(C0f?l?!4B(B, $(C5N9xB0(B $(CG`@G(B $(C<15N(B -$(C7N(B $(C0!<-(B, C-o $(C8&(B $(C@T7BGU4O4Y(B. - - >> $(C@{4gHw(B $(CG`@G(B $(C<15N?!(B $(C0!<-(B, $(C0E1b<-(B C-o $(C8&(B $(C@T7BGO?)(B $(C:8<z=@4O4Y(B. $(C9.@Z?M(B $(C00@L(B, $(C4\>n3*(B $(CG`55(B -$(C;hA&GR(B $(C`GO8i(B $(C4Y@=0z(B $(C00=@4O4Y(B. - - $(CD?<-Aw@|@G(B $(C9.@Z8&(B $(C;hA&(B - C-d $(CD?<-0!(B $(C@V4B(B $(C9.@Z8&(B $(C;hA&(B - - ESC $(CD?<-Aw@|@G(B $(C4\>n8&(B $(C;hA&(B - ESC d $(CD?<-@'D!(B $(C@LHD?!(B $(C@V4B(B $(C4\>n8&(B $(C;hA&(B - - C-k $(CD?<-@'D!7N:NEM(B $(CG`3!1nAv8&(B $(C;hA&(B - - $(C9+>y@N0!8&(B $(C;hA&GQ(B $(CHD?!(B, $(C1W0M@;(B $(C?x7!4k7N(B $(C5G598.0m(B $(C=M@;(B $(C6'0!(B $(C@V=@4O(B -$(C4Y(B. Emacs$(C4B(B, $(CGQ9.@Z:84Y(B $(CE+(B $(C4\@'7N(B $(C;hA&8&(B $(CG`GQ(B $(C6'?!4B(B, $(C;hA&GQ(B $(C3;?k@;(B -$(C:8A8GO?)(B $(C5S4O4Y(B. $(C?x7!4k7N(B $(C5G598.4B5%4B(B, C-y $(C8&(B $(C;g?kGU4O4Y(B. $(CAV@GGX>_(B -$(CGO4B(B $(C0M@:(B, C-y $(C8&(B $(C;hA&8&(B $(CG`GQ(B $(C@eF4O6s(B, $(C>n5p?!<-6s55(B $(CGR(B $(Cn@L9G7N(B, $(C@L0M@;(B $(C;g?kGO?)(B $(CEX=:F.8&(B $(C@L5?GR(B $(Cn?!4B(B, "Delete" $(C8m7I>n?M(B, "Kill" $(C8m7I>n0!(B $(C@V=@(B -$(C4O4Y(B. "Kill" $(C8m7I>n?!<-4B(B $(C;hA&5H(B $(C0M@:(B $(C:8A85GAv88(B, "Delete"$(C?!<-4B(B $(C:8A8(B -$(C5GAv(B $(C>J=@4O4Y(B. $(C4\(B, $(C9]:9H8nAv8i(B, $(C:8A85K4O4Y(B. - - >> C-n $(C@;(B 2$(CH8(B $(CA$55(B $(CE8@LGAGO0m(B, $(CH-8i@G(B $(C@{4gGQ(B $(C@e`(B, C-k $(C?!(B $(C9]:9H8(B $(C> C-y $(C8&(B $(C=CGhGO?)(B $(C:8<n(B $(C:8A85G(B -$(C0m(B, C-y$(C7N(B, $(C1W(B $(C@|:N0!(B $(C2t3;>nA}4O4Y(B. - - >> C-k $(C8&(B $(C8n9x(B $(CE8@LGAGO?)(B $(C:8<> $(CEX=:F.8&(B $(C2t3;4B5%4B(B, C-y $(C@T4O4Y(B. $(CD?<-8&(B $(C8nG`(B $(C9X@87N(B $(C@L5?=CE0(B - $(C0m(B, $(CGQ9x(B $(C4u(B C-y $(C8&(B $(CE8@LGAGO?)(B $(C:8<n62(B $(CEX=:F.0!(B $(C:8A85G>n(B $(C@V0m(B, $(C4u183*(B $(C4Y8%(B $(CEX=:F.8&(B $(C;hA&GO8i(B -$(C>n6;0T(B $(C5G0Z=@4O1n(B? C-y$(C4B(B, $(C0!@e(B $(CCV1Y(B $(C;hA&5H(B $(C0M@;(B $(C2tA}>n3@4O4Y(B. - - >> $(CG`@;(B $(C;hA&GO0m(B, $(CD?<-8&(B $(C@L5?=CE00m(B, $(C4Y8%(B $(CG`@;(B $(C;hA&GO<pA&6s55(B, $(CEX=:F.8&(B $(C:/0fGO?4Av88(B, $(C1W0M@;(B $(C?x7!4k7N(B $(C5G598.0m(B $(C=M@;(B $(C6'(B -$(C4B(B C-x u$(C7N(B $(C0mD(4O4Y(B. $(C:8Ek@:(B $(C@_8x5H(B $(C8m7I>n8&(B $(C9+H?7N(B $(CGO4B(B $(C@[5?@;(B $(CGU4O4Y(B. -$(C9]:9GX<-(B UNDO$(C8&(B $(CG`GO7A0m(B $(CGR(B $(C6'4B(B, $(C8n9x@L3*(B $(C1W(B $(C8m7I>n8&(B $(CG`GO8i(B $(C5G557O(B -$(C5G>n(B $(C@V=@4O4Y(B. - - >> $(C@L(B $(CG`@;(B C-k$(C7N(B $(CAv?l<n@T4O4Y(B. $(C1b4I@:(B, C-x u$(C?M(B $(C00(B - $(C=@4O4Y(B. - - C-_$(C3*(B C-x u$(C?!(B UNDO$(C@G(B $(CH8_(B $(CGU4O4Y(B. $(C:8A8GOAv(B $(C>J@88i(B, $(CG`GQ(B $(C:/0f@:(B, Emacs$(C8&(B $(CA>7aGO8i(B $(C5?=C?!(B $(C@R>n(B -$(C9v8.0T(B $(C5K4O4Y(B. - - $(CAv1](B $(C:80m(B $(C@V4B(B $(CH-@O?!(B $(C4kGX<-(B, $(C4g=E@L(B $(CFmA}@;(B $(CG`GQ(B $(C0M@;(B $(C=a3V=@4O4Y(B. -$(CAv1](B, $(C:80m(B $(C@V4B(B $(CH-@O@L6u(B $(C0M@:(B, $(C0#4\Hw(B $(C8;GO8i(B $(CFmA}GO0m(B $(C@V4B(B $(CH-@O(B $(C@ZC<@T(B -$(C4O4Y(B. - - $(C4g=E@L(B $(CH-@O@;(B $(C<<@L:j(B($(C:8A8GQ4Y(B)$(CGO1b(B $(C1nAv(B, $(CAv1]1nAv@G(B $(C:/0f@:(B $(CFmA}GO(B -$(C0m@V4B(B $(CH-@O?!(B $(C=a3V4B(B $(C0M@:(B $(C>F4U4O4Y(B. $(C1W0M@:(B, $(C4g=E@L(B $(C@L?M(B $(C00@L(B $(C:/0fGO0m(B -$(C=MAv(B $(C>J@:5%55(B, $(C55A_1nAv(B $(C:/0f@;(B $(C0!GQ(B $(C0M@L(B $(CA&8Z4k7N(B $(C=a3V>nAv4B(B $(C@O@L(B $(C>x55(B -$(C7O(B $(CGO1b(B $(C@'GX<-(B $(C@T4O4Y(B. - - $(C<<@L:j@;(B $(CG`GQ(B $(C5ZA6Bw(B $(C:/0fGQ(B $(C0M@L(B $(C@_8x(B $(C5G>n(B $(C@V@;(B $(C6'8&(B $(C@'GO?)(B Emacs -$(C4B(B $(C@L8'@;(B $(C:/0fGO?)(B $(C?x:;(B $(CH-@O@;(B $(C321i4O4Y(B. - -$(C:q0m(B: $(C6GGQ(B, Emacs$(C4B(B $(C?9CxGR(B $(Cx4B(B $(C;sEB?!(B $(C4k:qGO?)(B, $(C@OA$GQ(B $(C=C(B - $(C0#0#0]@87N(B $(C@Z5?@{@87N(B $(CFmA}GO0m(B $(C@V4B(B $(CH-@O@G(B $(C3;?k@;(B $(C@L8'(B - $(C@;(B $(C:/0fGQ(B $(CH-@O?!(B $(C<<@L:jGU4O4Y(B. $(C@L0M?!(B $(C@GGX(B, $(C88@O@G(B $(C0f?l(B - $(C4B(B $(CG`GQ(B $(C:/0f?!(B $(C4kGO?)(B $(CCVF7!(B $(CBJ@;(B $(C:88i(B, $(C@L?M(B $(C00@:(B $(C6f@87N(B $(C8p5e6s@N@L(B $(CG%=C5G>n(B $(C@V4Y(B -$(C0m(B $(C;}0"GU4O4Y(B. - -($(C?9(B) [--]J:--**-Mule: MULE.tut (Fundamental) ---55%-------------- - - - $(C@L(B Emacs$(CF)Ed8.>s@G(B $(C:9;g:;@:(B MULE.tut$(C@L6s0m(B $(C:R8.0m(B $(C@V=@4O4Y(B. $(CH-@O(B -$(C@;(B $(CH-@N5e(B($(CH-@O@;(B $(CC#>F<-(B $(C9vF[?!(B $(C@P>n3V4B(B $(C0M(B)$(CGO8i(B, MULE.tut$(C@G(B $(C:N:P?!(B $(CG%=C(B -$(C5K4O4Y(B. $(C?98&(B $(C5i8i(B, new-file$(C@L6s4B(B $(C@L8'@G(B $(CH-@O@;(B $(CH-@N5eGO?44Y8i(B, "Mule: -new-file"$(C@L6s4B(B $(C8p5e6s@N@L(B $(C5G0ZAv?d(B. - -$(CAV@G(B: $(C8p5e6s@N?!(B $(C4kGX<-4B(B $(C3*A_?!(B $(C<38mGO0Z=@4O4Y(B. $(C@a1q(B $(C1b4Y8.=C(B - $(C1b8&(B. - - $(CH-@O@;(B $(CH-@N5eGO0E3*(B, $(C<<@L:jGO4B(B $(C8m7I>n4B(B, $(CAv1]1nAv@G(B $(C0M0z4B(B $(C4^8.(B, -2$(C03@G(B $(C9.@Z7N(B $(C5G>n(B $(C@V=@4O4Y(B. C-x $(C?!(B $(C@L>n<-(B $(C@T7BGO4B(B $(C9.@Z0!(B, $(CH-@O?!(B $(C4kGX(B -$(C<-(B $(CG`GO4B(B $(CA6@[@;(B $(C3*E83@4O4Y(B. - - $(CGQ0!Av(B $(C4u(B, $(CAv1]1nAv@G(B $(C0M0z(B $(C4Y8%(B $(CA!@:(B, $(CH-@N5e(B $(C=C(B, $(CH-@O8m@;(B Emacs$(C0!(B -$(C90>n:>4O4Y(B. $(C@L0M@;(B, $(C4\8;7N:NEM(B $(C@Nn5i?)?@4B(B $(C8m7I>n6s0m(B $(C8;GO0m(B -$(C@V=@4O4Y(B. - - -$(CAV@G(B: $(C@L(B $(C0f?l4B(B $(CH-@O8m(B $(C@T4O4Y(B. - - C-x C-f $(CH-@O@;(B $(CC#4B4Y(B($(CH-@N5eGQ4Y(B) - - Emacs$(C4B(B $(CH-@O8m@;(B $(C90>n?I4O4Y(B. $(C@L0M@:(B, $(CH-8i9X@G(B $(CG`?!(B $(C3*E8334O4Y(B. -$(CH-@O8m@;(B $(CAvA$GO0m(B $(C@V4B(B $(C:N:P@:(B, $(C9L4O9vF[6s0m(B $(C:R8.?l4B(B $(C0M@T4O4Y(B. $(C9L4O9v(B -$(CF[4B(B $(C@L?M(B $(C00@L(B $(C;g?k5K4O4Y(B. $(CH-@O8m?!(B $(C@L>n<-(B, $(C8.4xE08&(B $(C4)8#8i(B, $(C9L4O9vF[(B -$(C?!(B $(CG%=C5G>nAx(B $(C3;?k@:(B $(C4u(B $(CGJ?dGOAv(B $(C>J1b(B $(C6'9.?!(B $(CAv?vA.(B $(C9v834O4Y(B. - - >> C-x C-f$(C6s0m(B $(CE8@LGAGQ(B $(C5Z?!(B C-g$(C6s0m(B $(CE8@LGAGO<n55(B $(CCkn62(B $(CH-@O55(B $(CC#Av(B $(C>J=@4O4Y(B. - - $(C@L9x?!4B(B $(CH-@O@;(B $(C<<@L:jGO?)(B $(C:8<n8&(B $(C;g?kGU4O4Y(B. - - C-x C-s $(CH-@O@;(B $(C<<@L:jGQ4Y(B - - Emacs$(C@G(B $(C3;?k@:(B $(CH-@O?!(B $(C=a3;>nA}4O4Y(B. $(C<<@L:jGR(B $(C6'(B, $(C?x:;@G(B $(CH-@O@:(B $(C;u(B -$(C7N?n(B $(C@L8'@;(B $(C:Y?)<-(B $(C320\Av1b(B $(C@V@89G7N(B $(C3;?k@:(B $(C>x>nAvAv(B $(C>J=@4O4Y(B. $(C@L(B $(C;u(B -$(C7N?n(B $(C@L8'@:(B $(C?x:;@G(B $(CH-@O@G(B $(C@L8'?!(B '~'$(C8&(B $(C:Y@N(B $(C0M@T4O4Y(B. - - $(C%;<<@L:j0!(B $(C3!3*8i(B, Emacs$(C4B(B $(C<<@L:jGQ(B $(CH-@O@G(B $(C@L8'@;(B $(CG%=CGU4O4Y(B. - - >> C-x C-s$(C6s0m(B $(CE8@LGAGO0m(B $(CF)Ed8.>s@G(B $(C:9;g:;@;(B $(C<<@L:jGO<`(B, 2$(C9xB0@G(B $(CH-@O@;(B C-x C-f $(C7N(B $(C2(3;8i(B, 1$(C9xB0@G(B $(CH-@O@:(B Emacs$(C3;:N(B -$(C?!(B $(C32=@4O4Y(B. Emacs$(C3;:N?!(B $(C@V4B(B $(CH-@O7N:NEM(B $(CEX=:F.8&(B $(C@P>n3V>n(B $(C:8A8GO0m@V(B -$(C4B(B $(C0M@:(B $(C9vF[6s0m(B $(C:R8.?s4O4Y(B. $(CH-@O@;(B $(C2(3;4B(B $(C0M@:(B, Emacs$(C3;:N?!(B $(C;u7N?n(B -$(C9vF[8&(B $(C885l4O4Y(B. - - Emacs $(C3;?!(B $(C:8A8GO0m(B $(C@V4B(B $(C9vF[@G(B $(C8.=:F.8&(B $(C:84B5%4B(B, $(C4Y@=0z(B $(C00@L(B -$(CE8@LGAGU4O4Y(B. - - C-x C-b - - >> C-x C-b $(C6s0m(B $(CE8@LGAGO<n60GQ(B $(C@L8'@;(B $(C0.(B - $(C0m(B $(C@V4B0!(B, $(C1W8.0m(B, $(C>n60GQ(B $(CH-@O8m@;(B $(C:Y@L0m(B $(C@V4B(B $(C0M@N0!(B $(C0|B{(B - $(CGO<J4B(B $(C0M55(B $(C@V=@4O4Y(B. $(C?98&(B $(C5i8i(B, "*Buffer -List*" $(C6s4B(B $(CH-@O@:(B $(C>x=@4O4Y(B. $(C@L0M@:(B C-x C-b $(C?!(B $(C@GGO?)(B $(C885i>nAx(B $(C9vF[8.(B -$(C=:F.?!(B $(C4kGQ(B $(C9vF[@T4O4Y(B. - - $(C4g=E@L(B $(C:80m(B $(C@V4B(B Emacs$(C@)55?l3;?!(B $(C@V4B(B, $(C>n60GQ(B $(CEX=:F.6s55(B, $(C>n4@0M(B -$(C@N0!@G(B $(C9vF[3;?!(B $(C@V=@4O4Y(B. - - >> $(C9vF[8.=:F.8&(B $(CAv?l1b(B $(C@'GX(B C-x 1 $(C6s0m(B $(CE8@LGAGO<`(B, $(C>n62(B $(CH-@O@G(B $(CEX=:F.?!(B $(C:/0f@;(B $(CG`GO0m3*<-(B, $(C4Y8%(B $(CH-@O@;(B $(C2(3;>z(B -$(C4Y0m(B $(CG_4Y8i(B, $(CCVCJ@G(B $(CH-@O@:(B $(C<<@L:j5G>n(B $(C@VAv(B $(C>J=@4O4Y(B. $(C1W(B $(C:/0f@:(B Emacs -$(C3;:N@G(B $(CH-@O0z(B $(C4k@@GO4B(B $(C9vF[(B $(C3;?!88(B $(CG`GO?)A.(B $(C@V=@4O4Y(B. - - 2$(C9xB0@G(B $(CH-@O?!(B $(C4k@@GO4B(B $(C9vF[8&(B $(C885i1b55GO0m(B, $(C?!5pF.GO4u6s55(B, 1$(C9x(B -$(CB0@G(B $(CH-@O?!(B $(C4k@@GO4B(B $(C9vF[?!4B(B $(C>F9+71(B $(C?5Gb@;(B $(CAVAv(B $(C>J=@4O4Y(B. $(C@L0M@:(B $(C4k(B -$(C4\Hw(B $(C;g?kGO1b(B $(C=10T(B, $(C6GGQ(B, 1$(C9xB0@G(B $(CH-@O?!(B $(C4k@@GO4B(B $(C9vF[8&(B $(CH.:8GO?)(B $(C5N(B -$(C1b(B $(C@'GO?)(B $(C55?r@L(B $(C5G4B(B $(C9f9}@T4O4Y(B. - - C-x C-s $(C7N(B $(C9vF[8&(B $(C<<@L:jGO1b(B $(C@'GO?)(B C-x C-f $(C7N(B $(C9vF[8&(B $(C13CF7!@G(B $(C8m7I>n8&(B $(C;g?kGU4O4Y(B. - - C-x s $(CGv@g(B $(C@V4B(B $(C9vF[8&(B $(C<<@L:jGQ4Y(B. - - C-x s $(C4B(B $(C3;?k@;(B $(C9Y2[(B $(C9vF[(B $(C@|C<8&(B $(CH-@O?!(B $(C<<@L:jGU4O4Y(B. $(C@L(B $(C6'(B, $(CGO3*(B -$(CGO3*@G(B ($(C<<@L:j5G>n>_(B $(CGR(B)$(C9vF[?!(B $(C4kGO?)(B, $(C<<@L:jGO4B0!(B, $(CGOAv(B $(C>J4B0!8&(B y$(C3*(B -n$(C@87N(B $(C9/=@4O4Y(B. $(C@L(B $(CG%=C4B(B $(CH-8i(B $(C9X@G(B $(CG`?!(B $(CG%=C5K4O4Y(B. $(C?98&(B $(C5i8i(B, $(C>F7!?M(B -$(C00=@4O4Y(B. - - Save file /usr/private/yours/MULE.tut? (y or n) - - - -$(C8m7I>n@G(B $(CH.@e(B -============= - - $(C?!5pEM?!4B(B, $(CD\F.7Q(B*$(CE03*(B $(C8^EM(B*$(CE07N(B $(C@T7BGR(B $(C@(B -$(C89@:(B $(C8m7I>n0!(B $(C@V=@4O4Y(B. $(C@L0M5i@;(B $(C4Y7g1b(B $(C@'GO?)(B, $(CH.@e(B(eXtend) $(C8m7I>n8&(B -$(C;g?kGU4O4Y(B. $(C@L0M?!4B(B, $(C>F7!@G(B 2$(C0!Av(B $(CA>7y0!(B $(C@V=@4O4Y(B. - - C-x $(C9.@Z?!(B $(C@GGQ(B $(CH.@e(B. $(C@L>n<-(B $(CGQ9.@Z8&(B $(C@T7BGU4O4Y(B. - ESC x $(C@L8'?!(B $(C@GGQ(B $(CH.@e(B. $(C@L>n<-(B $(C8m7I>n@G(B $(C@L8'@;(B $(C@T7BGU4O4Y(B. - - $(C@L0M5i@:(B $(C@O9]@{@87N(B, $(CFm8.GOAv88(B, $(CAv1]1nAv(B $(C:8>F?B(B $(C0M0z(B $(CA61](B $(C:s9xGO(B -$(C0T4B(B $(C;g?k5GAv(B $(C>J4B(B $(C8m7I>n8&(B $(C@'GQ(B $(C0M@T4O4Y(B. C-x C-f ($(CH-@N5e(B)$(C3*(B C-x C-s -($(C<<@L:j(B)$(C4B(B $(C@L(B $(C:N7y@T4O4Y(B. $(C@L?\?!(B, C-x C-c($(C?!5pEM@G(B $(CA>7a(B)$(C55(B $(C1W78=@4O4Y(B. - - C-z$(C4B(B Emacs$(C?!<-(B $(C:|A.3*?@4@5%?!(B $(C@ZAV(B $(C;g?k5G4B(B $(C9f9}@T4O4Y(B. Emacs$(C8&(B -$(CA>7aGO4B(B $(C0M@L(B $(C>F4O6s(B, $(C@O4\(B, csh$(C@G(B $(C79:'?!(B $(C5G59>F0!4B5%?!4B(B $(CA&@O(B $(CAA@:(B $(C9f(B -$(C9}@L6s0m(B $(C8;GR(B $(CF4U4O4Y(B. - -$(CAV@G(B: $(C4\(B, X-window$(C?!<-(B $(CG`GO0m(B $(C@V4B(B $(C0f?l(B, $(CH$@:(B $(C;g?kGO0m(B $(C@V4B(B - $(C=)@L(B sh$(C@O(B $(C6'4B(B, $(C1W78Av(B $(C>J=@4O4Y(B. - - C-x $(C8m7I>n4B(B,$(C89@L(B $(C@V=@4O4Y(B. $(C@L9L(B $(C9h?n(B $(C0M@:(B $(C>F7!@G(B $(C0M@T4O4Y(B. - - C-x C-f $(CH-@O@G(B $(CFmA}(B(Find) - C-x C-s $(CH-@O@G(B $(C:8A8(B(Save) - C-x C-b $(C9vF[8.=:F.@G(B $(CG%=C(B - C-x C-c $(C?!F7aGQ4Y(B. $(CH-@O@G(B $(C:8A8@:(B, $(C@Z5?@{@87N4B(B $(CG`GO?)(B - $(CAvAv(B $(C>J4B4Y(B. $(C1W7/3*(B, $(CH-@O@L(B $(C:/0f5G>n(B $(C@V@88i(B, $(CH-@O@G(B $(C:8(B - $(CA8@;(B $(CGO4B0!(B, $(C>F4Q0!8&(B $(C90>n?I4O4Y(B. $(C:8A8GO?)(B $(CA>7aGO4B(B $(C:8(B - $(CEk@G(B $(C9f9}(B, C-x C-s C-x C-c $(C7N(B $(CGO4B(B $(C0M@T4O4Y(B. - - $(C@L8'?!(B $(C@GGQ(B $(CH.@e8m7I>n?!4B(B, $(C1W4YAv(B $(C;g?k5GAv(B $(C>J4B(B $(C0M@L3*(B, $(CF/A$@G(B -$(C8p5e?!<-9[?!(B $(C;g?k5GAv(B $(C>J4B(B $(C0M5n@L(B $(C@V=@4O4Y(B. $(C?97N<-(B, "command-apropos" -$(C8&(B $(C5l4O4Y(B. $(C@L(B $(C8m7I>n4B(B $(CE0?v5e8&(B $(C@T7B=CE00m(B, $(C1W0M?!(B $(C8ED!GO4B(B $(C8p5g(B $(C8m7I(B -$(C>n@G(B $(C@L8'@;(B $(CG%=CGU4O4Y(B. ESC x $(C6s0m(B $(CE8@LGAGO8i(B, $(C=:E)80(B $(C9X?!(B "M-x" $(C0!(B $(CG%(B -$(C=C5K4O4Y(B. $(C@L0M?!(B $(C4kGO?)(B, $(C=GG`GO4B(B $(C8m7I>n@G(B $(C@L8'(B($(CAv1]@G(B $(C0f?l(B, -"command-apropos")$(C8&(B $(C@T7BGU4O4Y(B. "command-a" $(C1nAv(B $(C@T7BGQ(B $(C5Z(B $(C=:Fd@L=:(B -$(C8&(B $(CD!8i(B, $(C5Z@G(B $(C:N:P@:(B $(C@Z5?@{@87N(B $(C8^?vA}4O4Y(B. $(C@L(B $(CHD(B, $(CE0?v5e8&(B $(C90@89G7N(B, -$(C>K0m(B $(C=M@:(B $(C9.@Z?-@;(B $(CE8@LGAGU4O4Y(B. $(C6GGQ(B, $(CE0?v5e8&(B $(C@T7BGOAv(B $(C>J@88i(B, $(C8p5g(B -$(C8m7I>n0!(B $(CG%=C5K4O4Y(B. - - >> ESC x $(C8&(B $(CE8@LGAGO0m(B, $(C@L>n<-(B, "command-apropos" $(CH$@:(B - "command-a" $(C@L6s0m(B $(CE8@LGAGU4O4Y(B. $(C4Y@=?!(B, - "kanji"$(C@L6s0m(B $(CE8@LGAGU4O4Y(B. - - $(C3*E83-(B "$(C@)55?l(B"$(C8&(B $(CAv?l4B5%4B(B, C-x 1 $(C@L6s0m(B $(CE8@LGAGU4O4Y(B. - -$(C8p5e6s@N(B -======== - - $(C88>`(B $(CC5C5Hw(B $(C8m7I>n8&(B $(CCF4Y8i(B, $(CH-8i@G(B $(C9XBJ@G(B $(C?!DZ?!8.>n6s0m(B $(C:R8.4B(B -$(C@en4B(B $(CH-8i@G(B $(CA&@O(B $(C9X(B $(CG`@T4O4Y(B. $(C1W(B -$(C9Y7N(B $(C@'@G(B $(CG`@:(B, $(C8p5e6s@N@L6s0m(B $(C:R8.0m(B $(C@V=@4O4Y(B. $(C8p5e6s@N@:(B $(C@L7/GQ(B $(C=D@8(B -$(C7N(B $(CG%=C5G>n(B $(C@V0ZAv?d(B. - - [--]J:--**-Mule: MULE.tut (Fundamental) ---NN%-------------- - - -$(CAV@G(B: NN%$(C@G(B NN$(C@:(B $(C<}@Z0!(B $(C5i>n(B $(C@V=@4O4Y(B. $(C4g=E@L(B $(C;g?kGO0m(B $(C@V4B(B - Emacs$(C@G(B $(C8p5e6s@N0z(B $(C4Y8&(B $(CAv55(B $(C8p8#Av88(B, $(C4gH2GOAv(B $(C8;557O(B. - $(C?98&(B $(C5i8i(B, $(C=C0#@L3*(B uptime$(C@L(B $(CG%=C5G0m(B $(C@V4B(B $(C0M@:(B, - display-time$(C@L6s4B(B $(C1b4I@L(B $(C@[5?GO0m(B $(C@V1b(B $(C6'9.@T4O4Y(B. - - $(C@L(B $(CG`?!(B $(C@GGO?)(B $(C89@:(B $(C@/?kGQ(B $(CA$:80!(B $(C>r>nA}4O4Y(B. - - - $(CAv1](B, $(C4g=E@L(B $(C:80m(B $(C@V4B(B $(CH-@O8m@;(B $(CG%=CGO0m(B $(C@V=@4O4Y(B. NN%$(C@:(B $(CGv@g(B $(C=:(B -$(CE)80@'?!(B $(CH-@O@G(B $(CA&@O(B $(C@'?!<-:NEM(B $(C8n(B $(CF[<>F.B00!(B $(CG%=C5G0m(B $(C@V4B(B $(C0!8&(B $(C3*E8(B -$(C3;0m(B $(C@V=@4O4Y(B. $(CH-@O@G(B $(C0!@e(B $(CCVCJ8&(B $(CG%=CGO0m(B $(C@V@88i(B, --Top--$(C6s0m(B $(CG%=C5K(B -$(C4O4Y(B. $(CH-@O@G(B $(C0!@e(B $(CCVHD8&(B $(CG%=CGO0m(B $(C@V4Y8i(B, --Bot--$(C6s0m(B $(CG%=C5K4O4Y(B. $(CH-8i(B -$(C3;?!(B $(CH-@O(B $(C@|:N0!(B $(CG%=C5G0m(B $(C@V4Y8i(B, --All--$(C6s0m(B $(CG%=C5K4O4Y(B. - - $(C8p5e6s@N@G(B $(Cn60GQ(B $(C8p5e?!(B $(C5i>n@V4B(B $(C0!8&(B $(C3*E8(B -$(C3;0m(B $(C@V=@4O4Y(B. $(CGv@g4B(B, $(C5pFzF.@N(B Fundamental$(C?!(B $(C5i>n0!(B $(C@V=@4O4Y(B. $(C@L0M55(B -$(C8^@LA.8p5e@G(B $(CGO3*@G(B $(C?9@T4O4Y(B. - - Emacs$(C4B(B Lisp mode$(C3*(B Text mode$(C?M(B $(C00@L(B, $(C4Y8%(B $(CGA7N1W7%>p>n3*(B $(CEX=:F.(B -$(C?!(B $(C4kGO?)(B $(C?!5pF.8&(B $(CG`GO1b(B $(C@'GQ(B $(C8n0!Av@G(B $(C8^@LA.8p5e8&(B $(C0.0m(B $(C@V=@4O4Y(B. -$(C>n62(B $(C6'6s55(B $(C9]5e=C(B $(C>n4@0M@N0!@G(B $(C8^@LA.8p5e@G(B $(C;sEB7N(B $(C5G>n(B $(C@V=@4O4Y(B. - - $(C0"0"@G(B $(C8^@LA.8p5e4B(B $(C8n0!Av@G(B $(C8m7I>n8&(B $(C@|Gt(B $(C4Y8%(B $(CG`5?@87N(B $(CGO?)(B $(C9v(B -$(C834O4Y(B. $(C?98&(B $(C5i>n(B $(C:8=J4O4Y(B. $(CGA7N1W7%(B $(C3;?!(B $(C8m7I>n8&(B $(C885e4B(B $(C8m7I>n0!(B $(C@V(B -$(C=@4O4Y(B. $(C8m7I>n8&(B $(C>n60GQ(B $(CG|=D@87N(B $(CGO4B0!4B(B, $(C0"(B $(CGA7N1W7%>p>n?!(B $(C5{6s<-(B -$(C4Y8#Av88(B, $(C0"0"@G(B $(C8^@LA.8p5e4B(B, $(C9]5e=C(B $(C3V>nA]4O4Y(B. - - $(C0"0"@G(B $(C8^@LA.8p5e?!(B $(C5i>n0!1b(B $(C@'GQ(B $(C8m7I>n4B(B $(C8p5e8m@L(B $(CH.@e5H(B $(C0M@87N(B -$(C5G>n(B $(C@V=@4O4Y(B. $(C?98&(B $(C5i8i(B, M-x fundamental-mode$(C4B(B Fundamental$(C7N(B $(C5i>n0!(B -$(C1b(B $(C@'GQ(B $(C0M@T4O4Y(B. - - $(C88>`(B, $(C?5>n8&(B $(C?!5pF.GQ4Y8i(B, Text mode$(C7N(B $(C5i>n0)4O4Y(B. - - >> M-x text-mode $(C6s0m(B $(CE8@LGAGO<> C-h m $(C8&(B $(C;g?kGO?)(B Text mode$(C?M(B Fundamental mode$(C@G(B $(CBw@L8&(B $(C>K>F(B - $(C:8<> C-x 1$(C7N(B $(C55E%8UF.8&(B $(CH-8i@87N:NEM(B $(CAv?l<n(B $(C>KFD:*@;(B $(C1W4k7N(B $(C@T7BGR(B $(Cs@;(B $(C:8<n(B $(C@V=@4O4Y(B. Mule $(C@:(B, $(CH-@O@TCb7B(B, $(C@T7B(B, $(CH-8iCb7B?!(B $(C4kGO?)(B, $(C0"(B -$(C0"(B $(C5683@{@87N(B $(CDZ5eC<0h8&(B $(CAvA$=CE3(B $(C> $(C8p5e6s@N(B $(C@'?!(B "J:","S:", $(CH$@:(B "E:"$(C0!(B $(CG%=C5G>n(B $(C@V4B0!(B $(CH.@N(B - $(CGO<n(B $(C@L?\(B -$(C@G(B $(C9.@Z(B($(C@O:;>n(B, $(CGQ19>n5n(B)$(C55(B $(CG%=CGQ4Y4B(B $(C0M@;(B $(C3*E83;0m(B $(C@V=@4O4Y(B. J$(C4B(B -JUNET$(C@87N(B $(C;g?k5G0m(B $(C@V4B(B JIS $(CDZ5e(B, S $(C4B(B Shift-JIS, E $(C4B(B $(C@O:;>n(BEUC $(C8&(B $(C3*(B -$(CE83;0m(B $(C@V=@4O4Y(B. $(C4Y19>n(B $(CG%=C@G(B $(C@/9+4B(B C-x C-k t $(C7N(B ON/OFF$(C@G(B $(CEd1[@L(B $(C0!(B -$(C4IGU4O4Y(B. - - $(C4Y@=@G(B $(C?94B(B, $(C@O4\(B $(C4Y19>nG%=C8&(B OFF$(CGO0m3*<-(B, $(C4Y=C(B $(CGQ9x(B ON$(C@;(B $(CG`GO?)(B -$(C:>4O4Y(B. - - >> C-x C-k t$(C8&(B 2$(C9x(B $(CG`GO<n(B $(C@V@;(B $(C6'(B, $(C88>`(B $(C4g=E@L(B $(C;g?kGO0m(B $(C@V(B -$(C4B(B $(C4\8;?!(B $(C8^EM(B*$(CE00!(B $(C:Y>n(B $(C@V@88i(B, $(C@L=:DI@LGA(B*$(CE0(B $(C4k=E?!(B $(C1W0M@;(B $(C;g?kGO4B(B -$(C0M@L(B $(C0!4IGU4O4Y(B. $(C@L(B $(C6'(B, $(C8^EM(B*$(CE0@G(B $(C;g?k9f9}@:(B $(CD\F.7Q(B*$(CE0?M(B $(C00@L(B $(C4)8#8i<-(B -$(C9.@Z8&(B $(CE8@LGAGU4O4Y(B. ESC <$(C9.@Z(B>$(C55(B M-<$(C9.@Z(B>$(C55(B $(C00@:(B $(C@[5?@;(B $(CGU4O4Y(B. $(CAv1](B -$(C1nAv@G(B $(C<38m?!<-(B ESC <$(C9.@Z(B>$(C6s0m(B $(CG`GO0m(B $(C@V4x(B $(C0w@L(B, M-<$(C9.@Z(B>$(C7N(B $(C5K4O4Y(B. $(CAV(B -$(C@GGX>_(B $(CGO4B(B $(C0M@:(B, $(C=,GAF.(BJIS$(C3*(B EUC$(CDZ5e(B $(C6'4B(B $(C;g?kGR(B $(Cx=@4O4Y(B. - - $(CDZ5eC<0h@G(B $(C13C<4B(B, $(C0"0"@G(B $(C9vF[?!(B $(C4kGX<-88(B $(C@/H?GU4O4Y(B. $(C0"0"@G(B, $(CDZ(B -$(C5eC<0h(B $(CAvA$?!(B $(C4kGX<-4B(B, C-h a coding-system $(C@87N:<(B $(C> C-h a coding-system $(C@87N(B $(C3*?@4B(B $(C55E%8UF.(B $(C3;@G(B, - set-display-coding-system, set-file-coding-system, - set-process-coding-system $(C@G(B $(C<38m@;(B $(C@P>n:8<n4B(B, $(CD?<-@'D!(B $(C@LHD8&(B $(C0K;vGQ4Y8i(B, C-s, $(CD?<-@'D!(B $(C@L@|@L(B -$(C6s8i(B C-r $(C@T4O4Y(B. C-s $(C8&(B $(CE8@LGAGO8i(B, $(C?!DZ?!8.>n?!(B "I-search:"$(C6s4B(B $(C9.@Z?-(B -$(C@L(B $(CGA7RF.7N<-(B $(CG%=C5K4O4Y(B. ESC$(C8&(B $(C4)8#8i(B, $(CA>7a5K4O4Y(B. - - - >> C-s$(C7N(B $(C0K;v@L(B $(C=C@[5K4O4Y(B. $(C1W8.0m(B, $(CC5C5Hw(B 1$(C9.@Z>?(B "cursor"$(C6s4B(B - $(C4\>n8&(B $(C@T7BGU4O4Y(B. 1$(C9.@Z(B $(C@T7BGR(B $(C6'864Y(B, $(CD?<-4B(B, $(C>n6;0T(B $(C?rAw(B - $(C@T4O1n(B? - - >> $(CGQ9x(B $(C4u(B C-s $(C8&(B $(CE8@LGAGO8i(B, $(C4Y@=@G(B "cursor"$(C8&(B $(CC#@;(B $(C> $(C8&(B 4$(CH8(B $(C@T7BGO0m(B, $(CD?<-@G(B $(C?rAw@S@;(B $(C:8<> ESC$(C8&(B $(C4)8#0m(B, $(CA>7aGU4O4Y(B. - - $(CC#0m(B $(C=M@:(B $(C9.@Z?-@;(B $(CE8@LGAA_?!55(B, $(CE8@LGAGQ(B $(C9.@Z:N:P88@87N(B, $(C0K;v@;(B -$(C=C@[GU4O4Y(B. $(C4Y@=(B $(C9.@Z8&(B $(CC#4B5%4B(B, $(C4Y=C(B C-s$(C8&(B $(CE8@LGAGU4O4Y(B. $(C88>`(B, $(C9.@Z(B -$(C?-@L(B $(CA8@gGOAv(B $(C>J@88i(B, $(C8^<7a5K4O4Y(B. - - $(C0K;v=GG`A_?!(B, $(C8&(B $(C@T7BGO8i(B, $(C0K;v9.@Z?-@G(B $(CA&@O(B $(C5Z@G(B $(C9.@Z0!(B -$(CAv?vA}4O4Y(B. $(C1W8.0m3*<-(B, $(CD?<-4B(B, $(C@L@|9x@G(B $(C@'D!7N(B $(C5G59>F0)4O4Y(B. $(C?98&(B $(C5i(B -$(C8i(B, "cu"$(C6s0m(B $(CE8@LGAGO0m(B, $(CCVCJ@G(B "cu"$(C@G(B $(C@'D!?!(B $(CD?<-0!(B $(C?rAw?44Y0m(B $(CGU=C4Y(B. -$(C?)1b?!<-(B $(C8&(B $(C@T7BGO8i(B, $(C<-D!6s@N@G(B 'u'$(C0!(B $(CAv?vAv0m(B, $(CD?<-4B(B 'u'$(C8&(B -$(CE8@LGAGO1b(B $(C@|?!(B, $(CD?<-0!(B $(C@V>z4x(B 'c'$(C@G(B $(C@'D!7N(B,$(C@L5?GU4O4Y(B. - - $(C0K;v=GG`A_?!(B, C-s $(C3*(B C-r $(C@L?\@G(B $(CD\F.7Q9.@Z8&(B $(CE8@LGAGO8i(B, $(C0K;v@:(B -$(CA>7aGU4O4Y(B. - - C-s $(C4B(B, $(CGv@g@G(B $(CD?<-@'D!(B $(C@LHD?!(B $(C3*?@4B(B $(C0K;v9.@Z?-@;(B $(CC#=@4O4Y(B. $(C88>`(B, -$(C@L@|(B $(CBJ@;(B $(CC#0m(B $(C=M@88i(B, C-r $(C@;(B $(CE8@LGAGO4B(B $(C0M@87N(B, $(C?*9fGb0K;v@L(B $(C0!4IGU4O(B -$(C4Y(B. C-s $(C?M(BC-r $(C4B(B, $(C0K;v@G(B $(C9fGb@L(B $(C9]4k@O(B $(C;S(B, $(C@|:N(B $(C00@:(B $(C?rAw@S@;(B $(CGU4O4Y(B. - -$(C8.D?=C:j(B $(C?!5pFC(B $(C79:'(B - - $(C6'6'7N(B, ($(C:;@G(B $(C>F4O0T(B) $(C8.D?=C:j(B $(C?!5pFC(B $(C79:'@L6s0m(B $(C:R8.4B(B $(C;sEB?!(B $(C5i(B -$(C>n0!4B(B $(C6'0!(B $(C@V=@4O4Y(B. $(C8^@LA.8p5e@G(B $(CJ=@4O4Y(B. - - $(C8.D?=C:j(B $(C?!5pFC(B $(C79:'7N:NEM(B $(C:|A.3*?@1b(B $(C@'GX<-4B(B, M-x top-level -$(C@L6s0m(B $(CE8@LGAGU4O4Y(B. - - >> $(C=CGhGO?)(B $(C:8<z4x(B $(C0M@T4O(B -$(C4Y(B. M-x top-level$(C@:(B, $(C>F9+71(B $(C?5Gb@;(B $(CAV0m(B $(C@VAv(B $(C>J=@4O4Y(B. - - $(C8.D?=C:j(B $(C?!5pFC(B $(C79:'7N:NEM(B $(C:|A.3*?@4B(B $(C0M?!(B $(C4kGX<-4B(B C-g$(C4B(B $(C5hAv(B $(C>J(B -$(C=@4O4Y(B. - - -$(CGoGA(B -==== - - Emacs$(C?!4B(B, $(C89@:(B $(C55?r1b4I@L(B $(C@V0m(B, $(C?)1b?!<-(B, $(C@|:N8&(B $(C<38mGO4B(B $(C0M@:(B -$(C:R0!4IGU4O4Y(B. $(C1W7/3*(B, $(C>FAw(B $(C8p8#4B(B $(C89@:(B $(C1b4I@;(B $(C9h?l1b(B $(C@'GX<-4B(B, -$(C6s0m(B $(C:R8.4B(B C-h $(C8&(B $(CE8@LGAGO4B(B $(C0M@87N(B, $(C89@:(B $(CA$:88&(B $(C@Tn<-(B $(CGJ?dGQ(B $(C?In62(B $(C?I`(B, C-h $(C8&(B $(CE8@LGAGO0m3*<-(B $(C86@=@L(B $(C:/G_4Y8i(B, C-g $(C8&(B $(CE8@LGAGO8i(B, -$(CCkn<-(B $(CE08&(B $(C@T7BGO8i(B, $(C1W(B -$(C8m7I>n?!(B $(C4kGQ(B $(CB*@:(B $(C<38m@;(B $(CG%=CGU4O4Y(B. - - >> C-h c C-p $(C6s0m(B $(CE8@LGAGO?)(B $(C:8<oGO0m(B $(C@VAv(B $(C>J@:(B $(C8m7I>n55(B $(C;}0"GX(B $(C3>(B $(Cn55(B C-h c $(C@G(B $(C5Z?!(B $(C@L>n(B -$(CA}4O4Y(B. - - $(C4u?m(B $(C;s<K0m(B $(C=M@88i(B, c $(C4k=E?!(B k $(C8&(B $(CAvA$GU4O4Y(B. - - >> C-h k C-p $(C6s0m(B $(CE8@LGAGO?)(B $(C:8<n@G(B $(C@L8'0z(B $(C1b4I@L(B $(CG%=C5K4O4Y(B. $(C4Y(B $(C@P>z@88i(B, -C-x 1 $(C6s0m(B $(CE8@LGAGO8i(B, $(C:|A.3*?I4O4Y(B. - - $(C@L?\?!55(B $(C55?r@L(B $(C5G4B(B $(C?I> C-h f previous-line $(C@;(B $(CE8@LGAGO0m(B, $(C@;(B $(C4)8#<n8&(B $(C=GG`GO4B(B $(CFcn8&(B $(CG%=CGU4O4Y(B. $(C@L(B $(C8m7I>n5i@:(B $(C8p5N(B ESC x $(C7N(B $(C=GG`GR(B - $(C> C-h a file $(C>K0m(B $(CE8@LGAGO0m(B, $(C@;(B $(C4)8#<n8&(B $(CG%=CGU4O4Y(B. $(C6GGQ(B, - find-file $(C@L3*(B write-file$(C6s4B(B $(C@L8'@G(B C-x C-f $(C3*(B C-x C-w $(C?M(B $(C00(B - $(C@:(B $(C8m7I>n55(B $(CG%=C5K4O4Y(B. - -$(C3!@87N(B -====== - -$(C@XAv8;0m(B: $(CA>7aGO4B5%4B(B, C-x C-c $(C6s0m(B $(CGU4O4Y(B. - - - $(C@L(B $(C@T9.Fm@:(B, $(CCJ=I@Z?!0T55(B $(C>K1b(B $(C=10T(B $(CGO557O(B $(C@G55GO0m(B $(C@V=@4O4Y(B. -$(C1W7/9G7N(B, $(CH$=C(B $(C9+>y@N0!(B $(C@LGXGO1b(B $(C>n7A?n(B $(CA!@L(B $(C@V4Y8i(B, $(CH%@Z<-(B $(CG*3d(B -$(CGOAv(B $(C8;0m(B, $(CF.A}@;(B $(C@b>F(B $(CAV<`(B, EMACS $(C8&(B $(C8n@OA$55(B $(C;g?kGO0m(B $(C:88i(B, $(C1W0M@;(B $(C1W885P4Y4B(B $(C0M@:(B -$(C8xGO0T(B $(C5I(B $(C0M@T4O4Y(B. $(CCVCJ?!4B(B $(C>n8.5U@}GR(B $(CAv55(B $(C8p8#0Z=@4O4Y(B. $(C1W7/3*(B, -$(C1W0M@:(B $(C>n60GQ(B $(C?!5pEM6s55(B $(C6H(B $(C00=@4O4Y(B. EMACS $(C?M(B $(C00@L(B, $(C4k4\Hw(B $(C89@:(B $(C0M@L(B -$(C0!4IGQ(B $(C0f?l?!4B(B $(CF/Hw(B $(C1W780ZAv?d(B. $(C1W8.0m(B, EMACS $(C?!<-4B(B, $(C=GA&7N(B, $(C9+>y@L(B -$(C3*(B $(CGR(B $(Cn(B MicroEMACS (kemacs) $(C@T9.Fm(B" -$(C@;(B GNUE- macs (Nemacs)$(C@G(B Tutorial$(C?k@87N(B $(C0mCD>4(B $(C0M@T4O4Y(B. - - Jonathan Payne $(C?!(B $(C@GGQ(B "JOVE Tutorial" (19 January 86) $(C@;(B $(C:/0fGQ(B - $(C0M@L0m(B, $(C1W0M@:(B $(C?x7!(B, CCA-UNIX$(C@G(B Steve Zimmerman $(C?!(B $(C@GGX<-(B $(C:/0f5H(B, - MIT $(C@G(B "Teach-Emacs" $(C@T9.Fm(B (31 October 85) $(C@;(B ($(C4u?m(B) $(C:/0fGQ(B $(C0M@L(B - $(C>z=@4O4Y(B. - - Update - February 1986 by Dana Hoggatt. - - Update - December 1986 by Kim Leburg. - - Update/Translate - July 1987 by SANETO Takanori - -$(CF/:0GQ(B $(C0(;g(B -=========== - - $(CCVCJ?!(B $(C@L(B $(C@O:;>n9x?*@;(B $(C@[<:GQ(B, SANETO Takanori$(C>>(B. $(C@L(B $(C9.@e@:(B GMW + -Wnn + Nemacs$(C@;(B $(C;g?kGO?)(B $(C@[<:G_=@4O4Y(B. $(C1W?M(B $(C00@:(B $(CHG8"GQ(B $(CGA7N1W7%@;(B $(C885g(B -$(C8p5g(B $(C:P?!0T(B $(C0(;g@G(B $(C6f@;(B $(CG%GO0m(B $(C=M=@4O4Y(B. $(C9x?*@L6s5g0!(B, $(C@T7B(B $(C5n(B -$(C?)7/8p7N(B $(C55?M(B $(CAX(B $(CHDAvGO6s>(B, $(C4k4\Hw(B $(C0(;gGU4O4Y(B. - - - -$(C?@?*(B, $(C0EA~(B, $(C@L(B $(C?\@G(B $(C9.C%@:(B $(C>F7!@G(B $(C;g6w?!0T(B $(C@V=@4O4Y(B. - - $BNkLZM5?.(B hironobu@sra.co.jp - - -Update/Add - December 1987 by Hironobu Suzuki -Update/Add - November 1989 by Ken'ichi Handa -Update/Add - January 1990 by Shigeki Yoshida -Update/Add - March 1992 by Kenichi HANDA - - -$(C6G4Y8%(B $(C0(;g(B -=========== - - $(C@L(B $(C9.<-4B(B "$(C@O:;>n(B GNUEMACS(Mule) $(C@T9.Fm(B"$(C@;(B $(CGQ19>n7N(B $(C9x?*GO?)(B, -hemacs$(C7N(B $(C@[<:GQ(B $(C0M@T4O4Y(B. $(C@O:;>n9x?*@;(B $(C4c4gGQ(B $(C8p5g(B $(C:P(B, hemacs$(C8&(B -$(C039_GO?)(B $(CAV=E(B $(C:P(B, $(CF/Hw(B Mule$(C0z(B hemacs$(C@G(B $(CH/0f18C`?!(B $(C89@:(B $(C55?r@;(B $(CAX(B -$(C136G4kGP(B $(C3*0!?@?,18=G(B $(CA9>w;}@N(B Masashi SHIMBO$(C>>?M(B Katsuyoshi -Yamagami$(C>>?!0T(B $(C0(;g@G(B $(C6f@;(B $(C@|GU4O4Y(B. - - 1993. 9. 25 - - $(C136G4kGP(B $(C0xGP:N(B $(C@|1b0xGP0z(B $(C3*0!?@?,18=G(B - Dosam HWANG hwang@forest.kuee.kyoto-u.ac.jp diff -r f427b8ec4379 -r 41ff10fd062f etc/TUTORIAL.no --- a/etc/TUTORIAL.no Mon Aug 13 10:03:54 2007 +0200 +++ b/etc/TUTORIAL.no Mon Aug 13 10:04:58 2007 +0200 @@ -24,7 +24,7 @@ Viktig: for å avslutte Emacs trykker du C-x C-c. (To tegn.) Tegnene ">>" helt til venstre angir en veiledning slik at du kan prøve ut en kommando. For eksempel: -<> +<> >> Trykk C-v (View next screen) for å hoppe til neste skjermbilde. (kom igjen, hold ned control-tasten og trykk v). Fra nå av bør du gjøre dette hver gang du er ferdig med å lese et diff -r f427b8ec4379 -r 41ff10fd062f etc/e/README --- a/etc/e/README Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -Rebuild terminfo files with -TERMINFO=/etc tic *.ti diff -r f427b8ec4379 -r 41ff10fd062f etc/e/emancs Binary file etc/e/emancs has changed diff -r f427b8ec4379 -r 41ff10fd062f etc/e/emancs.ti --- a/etc/e/emancs.ti Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -emancs, - cols#80, - sgr0=\003, - smso=\001, - smul=\002, - rmul=\003, - it#1, diff -r f427b8ec4379 -r 41ff10fd062f etc/e/eterm Binary file etc/e/eterm has changed diff -r f427b8ec4379 -r 41ff10fd062f etc/e/eterm.ti --- a/etc/e/eterm.ti Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -# These are ordered as in the O'Reilly "termcap and terminfo" book. -eterm, - lines#24,cols#80, - cuu1=\E[A,cud1=\n,cub1=\b,cuf1=\E[C,home=\E[H,cr=\r, - cuu=\E[%p1%dA,cud=\E[%p1%dB,cub=\E[%p1%dD,cuf=\E[%p1%dC, - cup=\E[%i%p1%d;%p2%dH, - ind=\n,csr=\E[%i%p1%d;%p2%dr, - il1=\E[L,il=\E[%p1%dL, - clear=\E[H\E[J,ed=\\E[J,el=\E[K, - dl1=\E[M,dl=\E[%p1%dM,dch1=\E[P,dch=\E[%p1%dP, - kcub1=\E[D,kcuf1=\E[C,kcuu1=\E[A,kcud1=\E[B, - smir=\E[4h,rmir=\E[4l,ich=\E[%p1%d@,mir, - smcup=\E7\E[?47h,rmcup=\E[2J\E[?47l\E8, - ht=\t, - smso=\E[7m,rmso=\E[m, - smul=\E[4m,rmul=\E[m, - rev=\E[7m,bold=\E[1m,sgr0=\E[m, - bel=^G,xenl,am, diff -r f427b8ec4379 -r 41ff10fd062f etc/hypb-mouse.txt --- a/etc/hypb-mouse.txt Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -============================================================================== - Smart Keys -Context Action Key Assist Key -============================================================================== -Hyperbole - On a menu item Item is activated Item help - On an explicit button Button is activated Button help - Reading argument - 1st press at an arg value Value copied to minibuffer <- same - 2nd press at an arg value Value used as argument <- same - In minibuffer Minibuf arg is applied Completion help - On an implicit button Button is activated Button help - Within an outline cell Collapses and expands Shows tree props - Left of an outline cell Creates a klink Moves a tree - Wrolo Match Buffer Edits entries and mails to e-mail addresses - -Mouse or Keyboard Display Control - Line end, not end of buffer - smart-scroll-proportional - = t (default) Makes curr line top line Bottom line - = nil Scrolls up a windowful Scrolls down - End of Any Help buffer Screen restored to previous state - -Mouse-only Control - Modeline down & wind release Resize window height <- same - Drag from shared window side - or from left of scroll bar Resize window width <- same - Drag between windows Create/modify a link but Swap window buffers - Horizontal drag within window - Left to right Scroll to buffer end Split window across - Right to left Scroll to buffer begin Delete window - Vertical drag within window Split window sideways <- same - Diagonal drag within window Save ring screen-config Restore ring config - Click in modeline - Left window edge Bury buffer Unbury bottom buf - Right window edge Info Smart Key summary - Otherwise Action Key Hook Assist Key Hook - -Special Modes - C,C++,Objective-C,Java Modes Jumps to id/include def Jumps to next def - Java Cross-Reference Tag Jumps to identifier def Jumps to next def - Assembly Language Mode Jumps to id/include def Jumps to next def - Any Lisp or Fortran Mode Jumps to id def Jumps to next def - Emacs Lisp Compiler Error Jumps to def with error <- same - Grep or Occur Match Jumps to match source line <- same - Multi-buffer Occur Match Jumps to match source line <- same - Outline Major/Minor Modes Collapses, expands, and moves outline entries - Man Apropos Displays man page entry <- same - Man Pages Follows cross refs, file refs and C code refs - Buffer Menu Saves, deletes and displays buffers - -Emacs Info Reader - Menu Entry or Cross Ref Jumps to referent <- same - Up, Next or Prev Header Jumps to referent Jumps to prior node - File entry of Header Jumps to top node Jumps to (DIR) node - End of current node Jumps to next node Jumps to prev node - Anywhere else Scrolls up a windowful Scrolls down a wind - -Subsystems - Calendar Scrolls or shows appts Scrolls/marks dates - Dired Mode Views and deletes files from directory listing - GNUS News Reader Toggles group subscriptions, gets new news, - and browses articles - Mail reader and Summaries Browses, deletes and expunges messages - OO-Browser Browses classes and elements - Tar Mode Views and edits files from tar archive files - -Any other context (defaults) Hyperbole top menu Smart Key summary -============================================================================== diff -r f427b8ec4379 -r 41ff10fd062f etc/ida-logo.xpm --- a/etc/ida-logo.xpm Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ -/* XPM */ -static char * ida_name [] = { -"368 98 95 2", -/* pixels*/ -"a0 c #131313131313", -"a1 c #3d3d3d3d3d3d", -"a2 c #3e3e3e3e3e3e", -"a3 c #3c3c3c3c3c3c", -"a4 c #0e0e0e0e0e0e", -"a5 c #f0f0f0f0f0f0", -"a6 c #cfcfcfcfcfcf", -"a7 c #d2d2d2d2d2d2", -"a8 c #d5d5d5d5d5d5", -"a9 c #d3d3d3d3d3d3", -"b0 c #d6d6d6d6d6d6", -"b1 c #c7c7c7c7c7c7", -"b2 c #090909090909", -"b3 c #f1f1f1f1f1f1", -"b4 c #1a1a1a1a1a1a", -"b5 c #1c1c1c1c1c1c", -"b6 c #212121212121", -"b7 c #f4f4f4f4f4f4", -"b8 c #202020202020", -"b9 c #797979797979", -"c0 c #696969696969", -"c1 c #6b6b6b6b6b6b", -"c2 c #6f6f6f6f6f6f", -"c3 c #646464646464", -"c4 c #686868686868", -"c5 c #707070707070", -"c6 c #6e6e6e6e6e6e", -"c7 c #747474747474", -"c8 c #737373737373", -"c9 c #767676767676", -"d0 c #6c6c6c6c6c6c", -"d1 c #676767676767", -"d2 c #828282828282", -"d3 c #7b7b7b7b7b7b", -"d4 c #666666666666", -"d5 c #636363636363", -"d6 c #757575757575", -"d7 c #727272727272", -"d8 c #5f5f5f5f5f5f", -"d9 c #787878787878", -"e0 c #5c5c5c5c5c5c", -"e1 c #595959595959", -"e2 c #7d7d7d7d7d7d", -"e3 c #717171717171", -"e4 c #7a7a7a7a7a7a", -"e5 c #6a6a6a6a6a6a", -"e6 c #6d6d6d6d6d6d", -"e7 c #777777777777", -"e8 c #1f1f1f1f1f1f", -"e9 c #232323232323", -"f0 c #222222222222", -"f1 c #555555555555", -"f2 c #7c7c7c7c7c7c", -"f3 c #808080808080", -"f4 c #888888888888", -"f5 c #606060606060", -"f6 c #656565656565", -"f7 c #242424242424", -"f8 c #1e1e1e1e1e1e", -"f9 c #8e8e8e8e8e8e", -"g0 c #1d1d1d1d1d1d", -"g1 c #252525252525", -"g2 c #616161616161", -"g3 c #626262626262", -"g4 c #282828282828", -"g5 c #424242424242", -"g6 c #7e7e7e7e7e7e", -"g7 c #4f4f4f4f4f4f", -"g8 c #838383838383", -"g9 c #a5a5a5a5a5a5", -"h0 c #dfdfdfdfdfdf", -"h1 c #ffffffffffff", -"h2 c #b2b2b2b2b2b2", -"h3 c #f8f8f8f8f8f8", -"h4 c #fcfcfcfcfcfc", -"h5 c #ebebebebebeb", -"h6 c #969696969696", -"h7 c #c5c5c5c5c5c5", -"h8 c #b1b1b1b1b1b1", -"h9 c #2f2f2f2f2f2f", -"i0 c #e4e4e4e4e4e4", -"i1 c #363636363636", -"i2 c #000000000000", -"i3 c #4b4b4b4b4b4b", -"i4 c #060606060606", -"i5 c #2a2a2a2a2a2a", -"i6 c #474747474747", -"i7 c #323232323232", -"i8 c #525252525252", -"i9 c #3a3a3a3a3a3a", -"j0 c #2d2d2d2d2d2d", -"j1 c #343434343434", -"j2 c #1b1b1b1b1b1b", -"j3 c #181818181818", -"j4 c #171717171717", -"a0a1a1a2a2a2a2a2a2a2a1a2a2a2a2a2a2a2a2a2a1a2a2a2a1a2a2a2a2a2a1a1a1a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a1a2a2a1a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a2a2a2a1a2a2a2a2a2a1a1a1a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a1a2a2a1a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a2a2a1a1a2a2a2a2a2a1a1a1a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a1a2a2a1a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a1a2a2a2a2a2a2a2a2a2a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a2a2a1a1a2a2a2a2a2a1a1a1a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a1a2a2a2a2a1a3a2a2a2a2a2a2a2a2a2a1a2a2a2a2a2a2a2a2a2a2a2a4", -"a2a5a6a6a7a6a8a7a7a7a7a7a8a6a7a7a9a9a7a9a7a8a8a7a7b0b0b0a9a6a6a6a8a9a7a7a7a9a7a7a9a8a6a8a8a6a9a8a6a6b0a6a7a8a7a9a7a6a9a8b0a8a9a7a8a9a7a7a7a7a8a8a8a7b0b0a8a8b0a8a8a9a8b0a6a6b0a7a7b0a8b0a8a9a8a9a9a6a6a6a7a6a8a7a7a7a7a7a8a6a7a7a9a9a7a9a7a8a8a7a7b0b0b0a9a6a6a6a8a9a7a7a7a9a7a7a9a8a6a8a8a6a9a8a6a6b0a6a7a8a7a9a7a6a9a8b0a8a9a7a8a9a7a7a7a7a8a8a8a7b0b0a8b0b0a8a8a9a8b0a6a6b0a7a7b0a8b0a8a9a8a9a9a6a6a6a7a6a8a7a7a7a7a7a8a6a7a7a9a9a7a9a7a8a8a7a7b0b0b0a7a6a6a6a8a9a7a7a7a9a7a7a9a8a6a8a8a6a8a8a6a6b0a6a7a8a7a9a7a6a9a8b0a8a9a7a8a9a7a7a7a7a8a8a8a7b0b0a8b0b0a8a8a9a8b0a6a6b0a7a7b0a8b0a8a8a9a9a9a6a6a6a7a6a8a7a7a7a7a7a8a6a7a7a9a9a7a9a7a8a8a7a7b0b0b0a9a6a6a6a8a9a7a7a7a9a7a7a8a9a6a8a8a6a8a8a6a6b0a6a7a8a7a9a7a6a9a8b0a8a8a7a8a9a7a7a7a7a8a8a8a7b0b0a8a9b1b2", -"a1a6b3a8a7a7a7a6a6b0a7a6a7a7a7a7a7a8a7a8a9a8b0a7a9b0b0b0a7a6a8a7b0b0b0a8a7a6a6a9a8b0a8a7b0a6a6a6a7a7a6a7a7a6a8a7a6a7a8a8b0b0a8a9a7a7a9a7a7a7a9a8a8a7a8b0b0a8a8b0a8b0b0a7a6a6b0b0a8b0b0b0a8a9a8a8a6a6a9a8a7a7a7a6a6b0a7a6a7a7a7a7a7a8a7a8a9a8b0a7a9b0b0b0a7a6a8a7b0b0b0a8a7a6a6a9a8b0a8a7b0a6a6a6a7a7a6a7a7a6a8a7a6a7a8a8b0b0a8a9a7a7a9a7a7a7a9a8a8a7a8b0b0a8a8b0a8b0b0a7a6a6b0b0a8b0b0b0a8a9a8a8a6a6a9a8a7a7a7a6a6b0a7a6a7a7a7a7a7a8a7a8a9a8b0a7a9b0b0b0a7a6a8a7b0b0b0a8a7a6a6a9a8b0a8a7b0a6a6a6a7a7a6a7a7a6a8a7a6a7a8a8b0b0a8a9a7a7a8a7a7a7a9a8a8a7a8b0b0a8a8b0a8b0b0a7a6a6b0b0a8b0b0b0a8a9a8a8a6a6a9a8a7a7a7a6a6b0a7a6a7a7a7a7a7a8a7a8a9a8b0a7a9b0b0b0a7a6a8a7b0b0b0a8a7a6a6a9a8b0a9a7b0a6a6a6a7a7a6a7a7a6a8a7a6a7a8a8b0b0a8a8a7a7a9a7a7a7a9a8a8a7a8b0b0b1b4b2", -"a1a6b0b3a8a9a7a6a6b0a9a6a7a7a7a7a7a8a7a8a9b0b0a9a7b0b0b0a6a6b0a8a9b0b0a8a8a9a7a8b0b0a9a6b1a6a7a7a7a9a6a7a8a7a8a7b1a8a8b0a8a8a8a7a8a7a7a7a8a8b0a8a8a9a8a8b0a7a8a9a9b0b0a7a6a7a8b0b0b0b0a8a8a9a8a8a6a6b0a8a8a9a7a6a6b0a9a6a7a7a7a7a7a8a7a8a9b0b0a9a7b0b0b0a6a6b0a8a9b0b0a8a8a9a7a8b0b0a9a6b1a6a7a7a7a9a6a7a8a7a8a7b1a8a8b0a8a8a8a7a8a7a7a7a8a8b0a8a8a8a8a8b0a7a8a9a9b0b0a7a6a7a8b0b0b0b0a8a8a9a8a8a6a6b0a8a8a9a7a6a6b0a9a6a7a7a7a7a7a8a7a8a9b0b0a9a7b0b0b0a7a6b0a8a9b0b0a8a8a9a7a8b0b0a8a6b1b1a7a7a7a9a6a7a8a7a8a7b1a8a8b0a8a8a8a7a8a7a7a7a8a8b0a8a8a9a8a8b0a7a8a9a9b0b0a7a6a7a8b0b0b0b0a8a8a9a8a8a6a6b0a8a8a9a7a6a6b0a9a6a7a7a7a7a7a8a7a8a9b0b0a9a7b0b0b0a6a6b0a8a9b0b0a8a8a9a7a8b0b0a8a6b1b1a7a7a7a9a6a7a8a7a8a7b1a8a8b0a8a8a9a7a7a7a7a7a8a8b0a8a8a8a9a7b1b5b6b2", -"a2a7a8a7b3b3b3b3a5a5b3b3b3b3b3b3b3b3b3b3b3b7b3b3b3b3b7b7b3a5a5b3b3b3b3b3b3b3b3b3b7b3b3b3a5a5a5b3b3b3a5b3a5b3b3a5a5b3b3b7b3b3b3b3b3b3b3b7b3b3b3b3b3b3b3b7b3b3b3b3b3b3b3b3a5a5b3b3b3b7b7b3b3b3b3b7b3a5b3b3b3b3b3b3a5a5b3b3b3b3b3b3b3b3b3b3b3b7b3b3b3b3b7b7b3a5a5b3b3b3b3b3b3b3b3b3b7b3b3b3a5a5a5b3b3b3a5b3a5b3b3a5a5b3b3b7b3b3b3b3b3b3b3b7b3b3b3b3b3b3b3b7b3b3b3b3b3b3b3b3a5a5b3b3b3b7b7b3b3b3b3b7b3a5b3b3b3b3b3b3a5a5b3b3b3b3b3b3b3b3b3b3b3b7b3b3b3b3b7b7a5a5a5b3b3b3b3b3b3b3b3b3b7b7b3b3a5b3b3b3b3b3a5b3a5b3b3a5a5b3b3b7b3b3b3b3b3b3b3b7b3b3b3b3b3b3b3b7b3b3b3b3b3b3b3b3a5a5b3b3b3b7b7b3b3b3b3b7b3a5b3b3b3b3b3b3a5a5b3b3b3b3b3b3b3b3b3b3b3b7b3b3b3b3b7b7a5a5a5b3b3b3b3b3b3b3b3b3b7b7b3b3a5b3b3b3b3b3a5b3a5b3b3a5a5b3b7b3b7b3b3b3b3b7b3b7b3b3b3b3b3b3b3b1b4b5b8b2", -"a2a7b0a8b3b9c0c1c2c2c3c1c4c2c5c4b9c6c2c7c6c8c9d0d1d2d3d2d4d5c3c9d2d3c9c5d6b9d7c8c1c8c1d8c5c6c6c1d8d9c3c6c2c4e0e1c5c5c0e2b9c4b9c4d7e3b9c4c5b9c5c1c1c1d7e3e2e4d7e5e5d7e6e6d8c4e5c3e7c7e3c6c2e3d6c7e5c4e2d7e4b9c0c1c2c2c3c1c4c2c5c4b9c6c2c7c6c8c9d0d1d2d3d2d4d5c3c9d2d3c9c5d6b9d7c8c1c8c1d8c5c6c6c1d8d9c3c6c2c4e0e1c5c5c0e2b9c4b9c4d7e3b9c4c5b9c5c1c1c1d7e3e2e4d7e5e5d7e6e6d8c4e5c3e7c7e3c6c2e3d6c7e5c4e2d7e4b9c0c1c2c2c3c1c4c2c5c4b9c6c2c7c6c8c9d0d1d2d3d2d4d5c3c9d2d3c9c5d6b9d7c8c1c8c1d8c5c6c6c1d8d9c3c6c2c4e0e1c5c5c0e2b9c4b9c4d7e3b9c4c5b9c5c1c1c1d7e3e2e4d7e5e5d7e6e6d8c4e5c3e7c7e3c6c2e3d6c7e5c4e2d7e4b9c0c1c2c2c3c1c4c2c5c4b9c6c2c7c6c8c9d0d1d2d3d2d4d5c3c9d2d3c9c5d6b9d7c8c1c8c1d8c5c6c6c1d8d9c3c6c2c4e0e1c5c5c0e2b9c4b9c4d7c2b9c4c5b9c5c1c1c1d7e8e9f0b6b2", -"a2b0a8a8b7c5c8c1c6c1c1d5f1c1c0b9c0c7c6c7c2d6e7c4e6f2d3f3c7e3d5d6d2f4b9e6c9c9c8c1d2e4d7d5c2e6c1d8c5d8c7d7c8d8c4c2e4b9b9c5e4c5b9b9c1c1e2c5c5d7c1c1c1c4d7d7b9e6d4d5e3e5e3e5c0f5e5f6c8c7c6c2c2d7d3c7e2e4b9d7e4c5c8c1c6c1c1d5f1c1c0b9c0c7c6c7c2d6e7c4e6f2d3f3c7e3d5d6d2f4b9e6c9c9c8c1d2e4d7d5c2e6c1d8c5d8c7d7c8d8c4c2e4b9b9c5e4c5b9b9c1c1e2c5c5d7c1c1c1c4d7d7b9e6d4d5e3e5e3e5c0f5e5f6c8c7c6c2c2d7d3c7e2e4b9d7e4c5c8c1c6c1c1d5f1c1c0b9c0c7c6c7c2d6e7c4e6f2d3f3c7e3d5d6d2f4b9e6c9c9c8c1d2e4d7d5c2e6c1d8c5d8c7d7c8d8c4c2e4b9b9c5e4c5b9b9c1c1e2c5c5d7c1c1c1c4d7d7b9e6d4d5e3e5e3e5c0f5e5f6c8c7c6c2c2d7d3c7e2e4b9d7e4c5c8c1c6c1c1d5f1c1c0b9c0c7c6c7c2d6e7c4e6f2d3f3c7e3d5d6d2f4b9e6c9c9c8c1d2e4d7d5c2e6c1d8c5d8c7d7c8d8c4c2e4b9b9c5e4c5b9b9c1c1e2c5c5d7c1c1c1c4d7b6f7b8f8b2", -"a2b0b0a9b3c5c6c6c2d5c3c3d5c5c4c4e4c8b9c9d7c9d6d5e6c2d9d2c8e6d4c5f9d7c6c9e6f2c1b9d2d3e5c1c0c2d5c2e1e5c8c6e5c2d4b9c5c0d7b9c5e4c2c5c1d5b9c5c4c5c1d7e3c6c6b9d7c4f5f5c1d4c3d6d1e1d4d7b9b9d7c1c9d6c7c7e2b9e4c5c5c5c6c6c2d5c3c3d5c5c4c4e4c8b9c9d7c9d6d5e6c2d9d2c8e6d4c5f9d7c6c9e6f2c1b9d2d3e5c1c0c2d5c2e1e5c8c6e5c2d4b9c5c0d7b9c5e4c2c5c1d5b9c5c4c5c1d7e3c6c6b9d7c4f5f5c1d4c3d6d1e1d4d7b9b9d7c1c9d6c7c7e2b9e4c5c5c5c6c6c2d5c3c3d5c5c4c4e4c8b9c9d7c9d6d5e6c2d9d2c8e6d4c5f9d7c6c9e6f2c1b9d2d3e5c1d4c2d5c2e1e5c8c6e5c2d4b9c5c0d7b9c5e4c2c5c1d5b9c5c4c5c1d7e3c6c6b9d7c4f5f5c1d4c3d6d1e1d4d7b9b9d7c1c9d6c7c7e2b9e4c5c5c5c6c6c2d5c3c3d5c5c4c4e4c8b9c9d7c9d6d5e6c2d9d2c8e6d4c5f9d7c6c9e6f2c1b9d2d3e5c1d4c2d5c2e1e5c8c6e5c2d4b9c5c0d7b9c5e4c2c5c1d5b9c5c4c5c1d7e3c6c6f7b6g0b5b2", -"a2a8a8a7b3b9c8c1c1c3c1c3b9c5c5d5c5c8c5d6c8d6c9f5d0d1c5e7c1d4e6d2f4b9c2e3c8d9e6e4b9d9c2d5e0d8e0c5c4c5c1c8d8c2c5c5c4c5e4c5b9b9c1c1d5c1d7c5c5c5c5c5c6c1c4d7f2e6c3d7d1d5d1d1d5f5d5c8d9c8e5c5d7d7c5e6e2b9c5c4c5b9c8c1c1c3c1c3b9c5c5d5c5c8c5d6c8d6c9f5d0d1c5e7c1d4e6d2f4b9c2e3c8d9e6e4b9d9c2d5e0d8e0c5c4c5c1c8d8c2c5c5c4c5e4c5b9b9c1c1d5c1d7c5c5c5c5c5c6c1c4d7f2e6c3d7d1d5d1d1d5f5d5c8d9c8e5c5d7d7c5e6e2b9c5c4c5b9c8c1c1c3c1c3b9c5c5d5c5c8c5d6c8d6c9f5d0d1c5e7c1d4e6d2f4b9c2e3c8d9e6e4b9d9c2d5e0d8e0c5c4c5c1c8d8c2c5c5c4c5e4c5b9b9c1c1d5c1d7c5c5c5c5c5c6c1c4d7f2e6c3d7d1d5d1d1d5f5d5c8d9c8e5c5d7d7c5e6e2b9c5c4c5b9c8c1c1c3c1c3b9c5c5d5c5c8c5d6c8d6c9f5d0d1c5e7c1d4e6d2f4b9c2e3c8d9e6e4b9d9c2d5e0d8e0c5c4c5c1c8d8c2c5c5c4c5e4c5b9b9c1c1d5c1d7c5c5c5c5c5c6c1c4b6g1e8g0b2", -"a2a8a8b0b3c4c4e0c1d7b9b9c5c5c4c4c2c1d7d6c9e3c6c7c0e5c2d6e6d4e5d2d2c9d7e6d7b9c1b9d2c6d0d4d8c4d8c5e4c8c6e5c4d5c5c5c5c5b9d7c4c4c5c4c1c4c5d4b9d7c5c5c1e5c6d7c1e5c0d4c4d4c8c7e1d8d4d6c7d7e5c8c1d7c1e2b9c5b9e2c5c4c4e0c1d7b9b9c5c5c4c4c2c1d7d6c9e3c6c7c0e5c2d6e6d4e5d2d2c9d7e6d7b9c1b9d2c6d0d4d8c4d8c5e4c8c6e5c4d5c5c5c5c5b9d7c4c4c5c4c1c4c5d4b9d7c5c5c1e5c6d7c1e5c0d4c4d4c8c7e1d8d4d6c7d7e5c8c1d7c1e2b9c5b9e2c5c4c4e0c1d7b9b9c5c5c4c4c2c1d7d6c9e3c6c7c0e5c2d6e6d4e5d2d2c9d7e6d7b9c1b9d2c6d0d4d8c4d8c5e4c8c6e5c4d5c5c5c5c5b9d7c4c4c5c4c1c4c5d4b9d7c5c5c1e5c6d7c1e5c0d4c4d4c8c7e1d8d4d6c7d7e5c8c1d7c1e2b9c5b9e2c5c4c4e0c1d7b9b9c5c5c4c4c2c1d7d6c9e3c6c7c0e5c2d6e6d4e5d2d2c9d7e6d7b9c1b9d2c6d0d4d8c4d8c5e4c8c6e5c4d5c5c5c5c5b9d7c4c4c5c4c1c4c5d4b9d7c5c5c1e5c6b6e8e8e8b2", -"a2a8a8a7b3c2c4c4d7f2b9c4c5c1c4c4c5c4c5c9d7e3c2c5c3e5e6c6c0f5d4b9e4d7c2c5c1e2c2g2e2e5c1c1e0b9c4c5b9c8c6e1c2e0c2c4d7c5d7b9b9c4c1c1c5b9c5e4c5b9d7c5e5c1d1e4c1e5e4c3d4d7e3d7f6d5d7d6c8e6c5c8c1e6e4b9c5d7d7c4c8c2c4c4d7f2b9c4c5c1c4c4c5c4c5c9d7e3c2c5c3e5e6c6c0f5d4b9e4d7c2c5c1e2c2g2e2e5c1c1e0b9c4c5b9c8c6e1c2e0c2c4d7c5d7b9b9c4c1c1c5b9c5e4c5b9d7c5e5c1d1e4c1e5e4c3d4d7e3d7f6d5d7d6c8e6c5c8c1e6e4b9c5d7d7c4c8c2c4c4d7f2b9c4c5c1c4c4c5c4c5c9d7e3c2c5c3e5e6c6c0f5d4b9e4d7c2c5c1e2c2g2e2e5c1c1e0b9c4c5b9c8c6e1c2e0c2c4d7c5d7b9b9c4c1c1c5b9c5e4c5b9d7c5e5c1d1e4c1e5e4c3d4d7e3d7f6d5d7d6c8e6c5c8c1e6e4b9c5d7d7c4c8c2c4c4d7f2b9c4c5c1c4c4c5c4c5c9d7e3c2c5c3e5e6c6c0f5d4b9e4d7c2c5c1e2c2g2e2e5c1c1e0b9c4c5b9c8c6e1c2e0c2c4d7c5d7b9b9c4c1c1c5b9c5e4c5b9d7c5e5c1d1f0e8f8f0b2", -"a2a8a7a7b3c2d7b9d7d4c5c4c1c4c5c1c0c1c4c5c2c1e5c9c5e6c1c2e6g3f5e6c6e6c6c2d7e4c3c2e2d0c4d4e0c5c5c5c5c2d0c4c4e1c1c1c4d7b9d7c5c1d8c4c5c4b9c5d7c1d7c1e5c7e2b9e6c2f3c1d1c8c8c2c4g3d7c7c2d1d7e5e6b9d7c5c4c5c4c4c8c2d7b9d7d4c5c4c1c4c5c1c0c1c4c5c2c1e5c9c5e6c1c2e6g3f5e6c6e6c6c2d7e4c3c2e2d0c4d4e0c5c5c5c5c2d0c4c4e1c1c1c4d7b9d7c5c1d8c4c5c4b9c5d7c1d7c1e5c7e2b9e6c2f3c1d1c8c8c2c4g3d7c7c2d1d7e5e6b9d7c5c4c5c4c4c8c2d7b9d7d4c5c4c1c4c5c1c0c1c4c5c2c1e5c9c5e6c1c2e6g3f5e6c6e6c6c2d7e4c3c2e2d0c4d4e0c5c5c5c5c2d0c4c4e1c1c1c4d7b9d7c5c1d8c4c5c4b9c5d7c1d7c1e5c7e2b9e6c2f3c1d1c8c8c2c4g3d7c7c2d1d7e5e6b9d7c5c4c5c4c4c8c2d7b9d7d4c5c4c1c4c5c1c0c1c4c5c2c1e5c9c5e6c1c2e6g3f5e6c6e6c6c2d7e4c3c2e2d0c4d4e0c5c5c5c5c2d0c4c4e1c1c1c4d7b9d7c5c1d8c4c5c4b9c5d7c1d7c1e5c7e2f7e8b6g1b2", -"a2a7a9a7b3c6c2c2d5c5c5c5e2c2c5d7c5c1c2d7c6d7d7c8c9e6c1e3e6c3d5c1c6d0f6d5c8b9c4c5d7c1c1e0e1c5c5c5c4c2c8c2d5e0c1c1c4d7b9b9d5d5g3d7c1c4c5d7c5c4b9d7c5c5e2d3c0c2e5e6e5c7c9d7d1d5d7d0c6e6c9c1c1e2c5c5c5c4c5c6c2c6c2c2d5c5c5c5e2c2c5d7c5c1c2d7c6d7d7c8c9e6c1e3e6c3d5c1c6d0f6d5c8b9c4c5d7c1c1e0e1c5c5c5c4c2c8c2d5e0c1c1c4d7b9b9d5d5g3d7c1c4c5d7c5c4b9d7c5c5e2d3c0c2e5e6e5c7c9d7d1d5d7d0c6e6c9c1c1e2c5c5c5c4c5c6c2c6c2c2d5c5c5c5e2c2c5d7c5c1c2d7c6d7d7c8c9e6c1e3e6c3d5c1c6d0f6d5c8b9c4c5d7c1c1e0e1c5c5c5c4c2c8c2d5e0c1c1c4d7b9b9d5d5g3d7c1c4c5d7c5c4b9d7c5c5e2d3c0c2e5e6e5c7c9d7d1d5d7d0c6e6c9c1c1e2c5c5c5c4c5c6c2c6c2c2d5c5c5c5e2c2c5d7c5c1c2d7c6d7d7c8c9e6c1e3e6c3d5c1c6d0f6d5c8b9c4c5d7c1c1e0e1c5c5c5c4c2c8c2d5e0c1c1c4d7b9b9d5d5g3d7c1c4c5d7c5c4b9d7c5c5e2f7f8b6e8b2", -"a2a7a7a7b3c2c1d5c5c5c4d7c5c5c5b9c4c4c5d7c6c2e6c1c5e5d4d6e5e5c6d0c6d7g3f6e4e4c2d4c1c1d0f1e0c4c5c5c4c8c6g2e1c4c1d5c5c4e2c5c3c4d5c4c5c5d7b9c5d7c5d7c5e4d6d0c1c5c1c0c8c7e3c6f5g2e5e5e3e3c5c4c1b9c4c1c1c4c1c4c1c2c1d5c5c5c4d7c5c5c5b9c4c4c5d7c6c2e6c1c5e5d4d6e5e5c6d0c6d7g3f6e4e4c2d4c1c1d0f1e0c4c5c5c4c8c6g2e1c4c1d5c5c4e2c5c3c4d5c4c5c5d7b9c5d7c5d7c5e4d6d0c1c5c1c0c8c7e3c6f5g2e5e5e3e3c5c4c1b9c4c1c1c4c1c4c1c2c1d5c5c5c4d7c5c5c5b9c4c4c5d7c6c2e6c1c5e5d4d6e5e5c6d0c6d7g3f6e4e4c2d4c1c1d0f1e0c4c5c5c4c8c6g2e1c4c1d5c5c4e2c5c3c4d5c4c5c5d7b9c5d7c5d7c5e4d6d0c1c5c1c0c8c7e3c6f5g2e5e5e3e3c5c4c1b9c4c1c1c4c1c4c1c2c1d5c5c5c4d7c5c5c5b9c4c4c5d7c6c2e6c1c5e5d4d6e5e5c6d0c6d7g3f6e4e4c2d4c1c1d0f1e0c4c5c5c4c8c6g2e1c4c1d5c5c4e2c5c3c4d5c4c5c5d7b9c5d7c5d7c5e4d6e8e8b6e8b2", -"a2a6a7a8b3c6c5c4c1c5d7e2d7c4c5c5c4c5c6c2d7c2e6d7c6d1c1c0c1d1d4c3d8c3c1e5d2e4e2f9c4c8c6c5c1d5c5c4c4c8d7g2c2c1d5c1d7c5e4c5c5d5c1d7c5c5c5c1c1d7c5c5b9c7e2c4c4d3e7c7c7c2c6d0d4f5g2b9e3c2d2c4d1d7c5c4e0e0c1c2c6c2c5c4c1c5d7e2d7c4c5c5c4c5c6c2d7c2e6d7c6d1c1c0c1d1d4c3d8c3c1e5d2e4e2f9c4c8c6c5c1d5c5c4c4c8d7g2c2c1d5c1d7c5e4c5c5d5c1d7c5c5c5c1c1d7c5c5b9c7e2c4c4d3e7c7c7c2c6d0d4f5g2b9e3c2d2c4d1d7c5c4e0e0c1c2c6c2c5c4c1c5d7e2d7c4c5c5c4c5c6c2d7c2e6d7c6d1c1c0c1d1d4c3d8c3c1e5d2e4e2f9c4c8c6c5c1d5c5c4c4c8d7g2c2c1d5c1d7c5e4c5c5d5c1d7c5c5c5c1c1d7c5c5b9c7e2c4c4d3e7c7c7c2c6d0d4f5g2b9e3c2d2c4d1d7c5c4e0e0c1c2c6c2c5c4c1c5d7e2d7c4c5c5c4c5c6c2d7c2e6d7c6d1c1c0c1d1d4c3d8c3c1e5d2e4e2f9c4c8c6c5c1d5c5c4c4c8d7g2c2c1d5c1d7c5e4c5c5d5c1d7c5c5c5c1c1d7c5c5b9c7e2f8f8f7f0b2", -"a2a6a6a7b3c2b9d5c4e4e4c5e4c5b9c4b9c4c1c9d0c1d1e6d7d7d5c5e5f6e0d8d8c1e6d2e4e2f2d7c5c5c5c4c1d5c1c4c2c8e5c1c4d5d5c4e4b9c5d7c4c1c1c0c5c5d7c1c4c5c5d7c7e7d9c4c3d2f4d3d9b9c7c5f6f5e4d2c5c4f4e6d1d7c5c4e0g2c3c1c6c2b9d5c4e4e4c5e4c5b9c4b9c4c1c9d0c1d1e6d7d7d5c5e5f6e0d8d8c1e6d2e4e2f2d7c5c5c5c4c1d5c1c4c2c8e5c1c4d5d5c4e4b9c5d7c4c1c1c0c5c5d7c1c4c5c5d7c7e7d9c4c3d2f4d3d9b9c7c5f6f5e4d2c5c4f4e6d1d7c5c4e0g2c3c1c6c2b9d5c4e4e4c5e4c5b9c4b9c4c1c9d0c1d1e6d7d7d5c5e5f6e0d8d8c1e6d2e4e2f2d7c5c5c5c4c1d5c1c4c2c8e5c1c4d5d5c4e4b9c5d7c4c1c1c0c5c5d7c1c4c5c5d7c7e7d9c4c3d2f4d3d9b9c7c5f6f5e4d2c5c4f4e6d1d7c5c4e0g2c3c1c6c2b9d5c4e4e4c5e4c5b9c4b9c4c1c9d0c1d1e6d7d7d5c5e5f6e0d8d8c1e6d2e4e2f2d7c5c5c5c4c1d5c1c4c2c8e5c1c4d5d5c4e4b9c5d7c4c1c1c0c5c5d7c1c4c5c5d7c7e7b9g0g0g1g4b2", -"a2a7a7a7b3d0c4c5b9c1c4c1b9c1b9c3c2e3c2c8c0e5g2d0c2c6g2c5e5c3d8c4d0d6c0d3d2c2e4b9g5e5c5c4c4c5c1e5c5c2e5c5c4c4c1b9c4e4c5c5c4c4c4c1d7c5c5c4c5c5c5d7c5d7d7d1d4d2d2d3b9c7c7c8c2c1f2f3b9d5b9c1e3c8c7c5e5d1d1c1c2c1c4c5b9c1c4c1b9c1b9c3c2e3c2c8c0e5g2d0c2c6g2c5e5c3d8c4d0d6c0d3d2c2e4b9g5e5c5c4c4c5c1e5c5c2e5c5c4c4c1b9c4e4c5c5c4c4c4c1d7c5c5c4c5c5c5d7c5d7d7d1d4d2d2d3b9c7c7c8c2c1f2f3b9d5b9c1e3c8c7c5e5d1d1c1c2c1c4c5b9c1c4c1b9c1b9c3c2e3c2c8c0e5g2d0c2c6g2c5e5c3d8c4d0d6c0d3d2c2e4b9g5e5c5c4c4c5c1e5c5c2e5c5c4c4c1b9c4e4c5c5c4c4c4c1d7c5c5c4c5c5c5d7c5d7d7d1d4d2d2d3b9c7c7c8c2c1f2f3b9d5b9c1e3c8c7c5e5d1d1c1c2c1c4c5b9c1c4c1b9c1b9c3c2e3c2c8c0e5g2d0c2c6g2c5e5c3d8c4d0d6c0d3d2c2e4b9g5e5c5c4c4c5c1e5c5c2e5c5c4c4c1b9c4e4c5c5c4c4c4c1d7c5c5c4c5c5c5d7c5d7d7f8g0g1g4b2", -"a2a6a7a7b3c2d5c3c1c5c5c1c5c1c4d7e3e3c6c3c1c0c4d1c6c6d4e5c0d4c1c6c5c9b9g6d3e2b9b9b9c5c5c1c4c3c5e5c3d1e5c4c1e0c2b9c0b9c5b9d5d5d4c1c1d7b9c4d7c5d7b9c5d7c8d5c0d6b9d3b9c7c5c8c6d7e4c5c5b9d6d7c2e6c1e5g2c4d1c1c4c2d5c3c1c5c5c1c5c1c4d7e3e3c6c3c1c0c4d1c6c6d4e5c0d4c1c6c5c9b9g6d3e2b9b9b9c5c5c1c4c3c5e5c3d1e5c4c1e0c2b9c0b9c5b9d5d5d4c1c1d7b9c4d7c5d7b9c5d7c8d5c0d6b9d3b9c7c5c8c6d7e4c5c5b9d6d7c2e6c1e5g2c4d1c1c4c2d5c3c1c5c5c1c5c1c4d7e3e3c6c3c1c0c4d1c6c6d4e5c0d4c1c6c5c9b9g6d3e2b9b9b9c5c5c1c4c3c5e5c3d1e5c4c1e0c2b9c0b9c5b9d5d5d4c1c1d7b9c4d7c5d7b9c5d7c8d5c0d6b9d3b9c7c5c8c6d7e4c5c5b9d6d7c2e6c1e5g2c4d1c1c4c2d5c3c1c5c5c1c5c1c4d7e3e3c6c3c1c0c4d1c6c6d4e5c0d4c1c6c5c9b9g6d3e2b9b9b9c5c5c1c4c3c5e5c3d1e5c4c1e0c2b9c0b9c5b9d5d5d4c1c1d7b9c4d7c5d7b9c5d7c8b5g0f0e9b2", -"a2a6a8a7b3b9c1c2c2e4c5c1c0d5c6c9d6c6c6c0c1c4g2d1c6d1c4c0d4c4e6e6e3c2c9c8g6e4c5b9b9d7c5c2c5c2c3d8e1d4c8e0d8d5b9c5d7b9c5d7c5c1c4c1c4e2c5c5d7c5d7d7d7c8b9f6c3d9b9e7c8b9c7c5c5c6b9e4c5b9d3d7c2c0c3d5g2c4c2c4c5b9c1c2c2e4c5c1c0d5c6c9d6c6c6c0c1c4g2d1c6d1c4c0d4c4e6e6e3c2c9c8g6e4c5b9b9d7c5c2c5c2c3d8e1d4c8e0d8d5b9c5d7b9c5d7c5c1c4c1c4e2c5c5d7c5d7d7d7c8b9f6c3d9b9e7c8b9c7c5c5c6b9e4c5b9d3d7c2c0c3d5g2c4c2c4c5b9c1c2c2e4c5c1c0d5c6c9d6c6c6c0c1c4g2d1c6d1c4c0d4c4e6e6e3c2c9c8g6e4c5b9b9d7c5c2c5c2c3d8e1d4c8e0d8d5b9c5d7b9c5d7c5c1c4c1c4e2c5c5d7c5d7d7d7c8b9f6c3d9b9e7c8b9c7c5c5c6b9e4c5b9d3d7c2c0c3d5g2c4c2c4c5b9c1c2c2e4c5c1c0d5c6c9d6c6c6c0c1c4g2d1c6d1c4c0d4c4e6e6e3c2c9c8g6e4c5b9b9d7c5c2c5c2c3d8e1d4c8e0d8d5b9c5d7b9c5d7c5c1c4c1c4e2c5c5d7c5d7d7d7c8b9g0g0f0f7b2", -"a2a7a9a7b3c4c5f2e5d7c5d5c4c1c1c6c6c0d5c5c0d5d5d5c8c2d4c2d0e5c1e6c6e6c0c1e4e4c2c5d7c5c5c5d5c4c5c5c3c2c1e0d8c1b9b9b9d2e4e4c5c4c5c5c5b9c4c5d7c5d7b9c8d7d7c7c5c5c6b9d7b9c5c7c2e6e2b9d7c5d9e6c1d4c3e6d1d1c2c4c5c4c5f2e5d7c5d5c4c1c1c6c6c0d5c5c0d5d5d5c8c2d4c2d0e5c1e6c6e6c0c1e4e4c2c5d7c5c5c5d5c4c5c5c3c2c1e0d8c1b9b9b9d2e4e4c5c4c5c5c5b9c4c5d7c5d7b9c8d7d7c7c5c5c6b9d7b9c5c7c2e6e2b9d7c5d9e6c1d4c3e6d1d1c2c4c5c4c5f2e5d7c5d5c4c1c1c6c6c0d5c5c0d5d5d5c8c2d4c2d0e5c1e6c6e6c0c1e4e4c2c5d7c5c5c5d5c4c5c5c3c2c1e0d8c1b9b9b9d2e4e4c5c4c5c5c5b9c4c5d7c5d7b9c8d7d7c7c5c5c6b9d7b9c5c7c2e6e2b9d7c5d9e6c1d4c3e6d1d1c2c4c5c4c5f2e5d7c5d5c4c1c1c6c6c0d5c5c0d5d5d5c8c2d4c2d0e5c1e6c6e6c0c1e4e4c2c5d7c5c5c5d5c4c5c5c3c2c1e0d8c1b9b9b9d2e4e4c5c4c5c5c5b9c4c5d7c5d7b9c8d7c7b6b6e8b6b2", -"a2a7a6a7b3c5d5c4c5d5b9d7c4c6d1c2c2c4d5b9c4d5d8e5b9d7d0d7c0e5c1c6e3c5e5c1e4e4d5c4e2b9c5c1c4d5e0e1c2c2e6d5d5d4b9b9c0e4b9b9c4e2e4c5e2c5c5c1d7c4e4b9c5e6e3d7c5e6d3e2c2d7e5b9c6c5d7c5c5f4b9c1d1c0d1c1d1c1g2c1c4c5d5c4c5d5b9d7c4c6d1c2c2c4d5b9c4d5d8e5b9d7d0d7c0e5c1c6e3c5e5c1e4e4d5c4e2b9c5c1c4d5e0e1c2c2e6d5d5d4b9b9c0e4b9b9c4e2e4c5e2c5c5c1d7c4e4b9c5e6e3d7c5e6d3e2c2d7e5b9c6c5d7c5c5f4b9c1d1c0d1c1d1c1g2c1c4c5d5c4c5d5b9d7c4c6d1c2c2c4d5b9c4d5d8e5b9d7d0d7c0e5c1c6e3c5e5c1e4e4d5c4e2b9c5c1c4d5e0e1c2c2e6d5d5d4b9b9c0e4b9b9c4e2e4c5e2c5c5c1d7c4e4b9c5e6e3d7c5e6d3e2c2d7e5b9c6c5d7c5c5f4b9c1d1c0d1c1d1c1g2c1c4c5d5c4c5d5b9d7c4c6d1c2c2c4d5b9c4d5d8e5b9d7d0d7c0e5c1c6e3c5e5c1e4e4d5c4e2b9c5c1c4d5e0e1c2c2e6d5d5d4b9b9c0e4b9b9c4e2e4c5e2c5c5c1d7c4e4b9c5e6e3b6e8b8f7b2", -"a2a7a7a7b3c0c0c5c4d5d5c1d5c6c1e6c5f5d5c4d7c2e6e6d6d6c5d1c1c1e6c0e3e3d0c2e4b9c4b9c5c4c5b9c4e0e0e1c4e5c6d5d5c5c0d7e4b9b9b9c5c5e2b9c4c5c4c5d7c5e2e2c5d7d7c5c1c5g6d3e7c2b9d7c6c7e2c5d7f9d6c1d4d4d5e5d1e5c4c1b9c0c0c5c4d5d5c1d5c6c1e6c5f5d5c4d7c2e6e6d6d6c5d1c1c1e6c0e3e3d0c2e4b9c4b9c5c4c5b9c4e0e0e1c4e5c6d5d5c5c0d7e4b9b9b9c5c5e2b9c4c5c4c5d7c5e2e2c5d7d7c5c1c5g6d3e7c2b9d7c6c7e2c5d7f9d6c1d4d4d5e5d1e5c4c1b9c0c0c5c4d5d5c1d5c6c1e6c5f5d5c4d7c2e6e6d6d6c5d1c1c1e6c0e3e3d0c2e4b9c4b9c5c4c5b9c4e0e0e1c4e5c6d5d5c5c0d7e4b9b9b9c5c5e2b9c4c5c4c5d7c5e2e2c5d7d7c5c1c5g6d3e7c2b9d7c6c7e2c5d7f9d6c1d4d4d5e5d1e5c4c1b9c0c0c5c4d5d5c1d5c6c1e6c5f5d5c4d7c2e6e6d6d6c5d1c1c1e6c0e3e3d0c2e4b9c4b9c5c4c5b9c4e0e0e1c4e5c6d5d5c5c0d7e4b9b9b9c5c5e2b9c4c5c4c5d7c5e2e2c5d7d7e8b8e8g1b2", -"a1a9a7a6b3b9c5c1c4c4d8d5c2c6c5d0c2g2d5c5c9c2d7c6c8c8c8g7c1e6d1c0c5c2c5d4d0e4e2c5c5c5c9d7c4d5e1d5c1e5d1e0c5c4c5c5c5c5c4b9d7c5e2e2c2c5c1c4c5b9d7b9e6d7c5d7c5e5d2b9d6e5d7d6c5d7e7c8b9c7c7c1e5d5d1c0c3c2d1d5c4b9c5c1c4c4d8d5c2c6c5d0c2g2d5c5c9c2d7c6c8c8c8g7c1e6d1c0c5c2c5d4d0e4e2c5c5c5c9d7c4d5e1d5c1e5d1e0c5c4c5c5c5c5c4b9d7c5e2e2c2c5c1c4c5b9d7b9e6d7c5d7c5e5d2b9d6e5d7d6c5d7e7c8b9c7c7c1e5d5d1c0c3c2d1d5c4b9c5c1c4c4d8d5c2c6c5d0c2g2d5c5c9c2d7c6c8c8c8g7c1e6d1c0c5c2c5d4d0e4e2c5c5c5c9d7c4d5e1d5c1e5d1e0c5c4c5c5c5c5c4b9d7c5e2e2c2c5c1c4c5b9d7b9e6d7c5d7c5e5d2b9d6e5d7d6c5d7e7c8b9c7c7c1e5d5d1c0c3c2d1d5c4b9c5c1c4c4d8d5c2c6c5d0c2g2d5c5c9c2d7c6c8c8c8g7c1e6d1c0c5c2c5d4d0e4e2c5c5c5c9d7c4d5e1d5c1e5d1e0c5c4c5c5c5c5c4b9d7c5e2e2c2c5c1c4c5b9d7b9e6d7c5b6e8e8g1b2", -"a2a7a7a7b3b9c5c4c1c1c4c4c4d7e6d0c1f5d5c6c9d7e3c2c2d7c2f1d7d7c4e5d7c4e4d7c4e2e2c5c4d7d9d7d5c4e0d5e0e5c8e4c5c5c2c5e4c5c5c5b9d7e2b9c1c4e2b9b9e2b9c1c5d6d9e5e5c2b9c7c8c6e5c7e4c7b9c7d2d3c1e5c0c3c3c4d1d1c4c4c5b9c5c4c1c1c4c4c4d7e6d0c1f5d5c6c9d7e3c2c2d7c2f1d7d7c4e5d7c4e4d7c4e2e2c5c4d7d9d7d5c4e0d5e0e5c8e4c5c5c2c5e4c5c5c5b9d7e2b9c1c4e2b9b9e2b9c1c5d6d9e5e5c2b9c7c8c6e5c7e4c7b9c7d2d3c1e5c0c3c3c4d1d1c4c4c5b9c5c4c1c1c4c4c4d7e6d0c1f5d5c6c9d7e3c2c2d7c2f1d7d7c4e5d7c4e4d7c4e2e2c5c4d7d9d7d5c4e0d5e0e5c8e4c5c5c2c5e4c5c5c5b9d7e2b9c1c4e2b9b9e2b9c1c5d6d9e5e5c2b9c7c8c6e5c7e4c7b9c7d2d3c1e5c0c3c3c4d1d1c4c4c5b9c5c4c1c1c4c4c4d7e6d0c1f5d5c6c9d7e3c2c2d7c2f1d7d7c4e5d7c4e4d7c4e2e2c5c4d7d9d7d5c4e0d5e0e5c8e4c5c5c2c5e4c5c5c5b9d7e2b9c1c4e2b9b9e2b9c1c5d6d9e8e8e8f0b2", -"a1a7a7a7b3c5c0c2c1d5c5d7d4c6c2e6e1c4c1b9c9c6e3c6c2d9e4f1b9d7b9e5d6c4e4d7c4e2e2c5c2d7c6c4d5e0d5e0c5b9f2e4b9c5c1b9b9d5c1c4e4b9b9c5c4c5c5d7c5e2b9c5d7d6d7c1e6d7c5d7c6e5d7e7d7c5b9c5e2b9d7c0c3d1d1d1d5c0c3c1c4c5c0c2c1d5c5d7d4c6c2e6e1c4c1b9c9c6e3c6c2d9e4f1b9d7b9e5d6c4e4d7c4e2e2c5c2d7c6c4d5e0d5e0c5b9f2e4b9c5c1b9b9d5c1c4e4b9b9c5c4c5c5d7c5e2b9c5d7d6d7c1e6d7c5d7c6e5d7e7d7c5b9c5e2b9d7c0c3d1d1d1d5c0c3c1c4c5c0c2c1d5c5d7d4c6c2e6e1c4c1b9c9c6e3c6c2d9e4f1b9d7b9e5d6c4e4d7c4e2e2c5c2d7c6c4d5e0d5e0c5b9f2e4b9c5c1b9b9d5c1c4e4b9b9c5c4c5c5d7c5e2b9c5d7d6d7c1e6d7c5d7c6e5d7e7d7c5b9c5e2b9d7c0c3d1d1d1d5c0c3c1c4c5c0c2c1d5c5d7d4c6c2e6e1c4c1b9c9c6e3c6c2d9e4f1b9d7b9e5d6c4e4d7c4e2e2c5c2d7c6c4d5e0d5e0c5b9f2e4b9c5c1b9b9d5c1c4e4b9b9c5c4c5c5d7c5e2b9c5d7d6d7b8b8b6b6b2", -"a2a7a7a6b3c5c4c2c1d5c5e2d5c1c2d1c3c0c4c2c6c2c2c2c2d7c5f1c2d7b9e4d7c2c5c6e5b9c2d7c9c6c5c1d5d8e0d8f2b9b9e4b9b9b9c0c5c4d7b9c5e2b9c4d4d7c1c5d7e2b9c5c4d7c5e5d7d7c7c2d7c5d3d3d7c1e2c5d7d9c2c0c0c5d4d4d1c0e5d5c4c5c4c2c1d5c5e2d5c1c2d1c3c0c4c2c6c2c2c2c2d7c5f1c2d7b9e4d7c2c5c6e5b9c2d7c9c6c5c1d5d8e0d8f2b9b9e4b9b9b9c0c5c4d7b9c5e2b9c4d4d7c1c5d7e2b9c5c4d7c5e5d7d7c7c2d7c5d3d3d7c1e2c5d7d9c2c0c0c5d4d4d1c0e5d5c4c5c4c2c1d5c5e2d5c1c2d1c3c0c4c2c6c2c2c2c2d7c5f1c2d7b9e4d7c2c5c6e5b9c2d7c9c6c5c1d5d8e0d8f2b9b9e4b9b9b9c0c5c4d7b9c5e2b9c4d4d7c1c5d7e2b9c5c4d7c5e5d7d7c7c2d7c5d3d3d7c1e2c5d7d9c2c0c0c5d4d4d1c0e5d5c4c5c4c2c1d5c5e2d5c1c2d1c3c0c4c2c6c2c2c2c2d7c5f1c2d7b9e4d7c2c5c6e5b9c2d7c9c6c5c1d5d8e0d8f2b9b9e4b9b9b9c0c5c4d7b9c5e2b9c4d4d7c1c5d7e2b9c5c4d7c5e8b6b6b6b2", -"a2a7a6a7b3c5c5c1c2d8c1d7c1d5c1d1d1f6f5c2c1d1c3d7d7c5d8f1c6c9c6d7d7d6c9d9d5e5c5c2d7d7c4d8c1c4d9d2b9c8f2c5e4c2b9c4c4c5c2c5b9c5e2c1e5c5c1c4d7b9b9d7d7e7c9e2b9e2d3d3b9b9g6e4e2b9d7e5c8d3b9c0c0d7d7d1c2c0g2c4c2c5c5c1c2d8c1d7c1d5c1d1d1f6f5c2c1d1c3d7d7c5d8f1c6c9c6d7d7d6c9d9d5e5c5c2d7d7c4d8c1c4d9d2b9c8f2c5e4c2b9c4c4c5c2c5b9c5e2c1e5c5c1c4d7b9b9d7d7e7c9e2b9e2d3d3b9b9g6e4e2b9d7e5c8d3b9c0c0d7d7d1c2c0g2c4c2c5c5c1c2d8c1d7c1d5c1d1d1f6f5c2c1d1c3d7d7c5d8f1c6c9c6d7d7d6c9d9d5e5c5c2d7d7c4d8c1c4d9d2b9c8f2c5e4c2b9c4c4c5c2c5b9c5e2c1e5c5c1c4d7b9b9d7d7e7c9e2b9e2d3d3b9b9g6e4e2b9d7e5c8d3b9c0c0d7d7d1c2c0g2c4c2c5c5c1c2d8c1d7c1d5c1d1d1f6f5c2c1d1c3d7d7c5d8f1c6c9c6d7d7d6c9d9d5e5c5c2d7d7c4d8c1c4d9d2b9c8f2c5e4c2b9c4c4c5c2c5b9c5e2c1e5c5c1c4d7b9b9d7d7e7c9e9f7e9f7b2", -"a2a7a6a9b3c5b9c6c1d8c2d6e6c2c3d4d7e1d8c2c6d5d1d5d1c4c1d7c6d6d7c9c9c8e2d9d5e5b9c5c5c5c4c4d5d6e4b9c5e4c5c5b9c4c4c1c1e2c5c5d7e2e4c4e4c5c1c4f2b9d7c5b9b9c5b9c9e7d3b9e4e4f2e2e2e3d7e5d7d9e6c1d4c5c2c1c2c0f5e6c4c5b9c6c1d8c2d6e6c2c3d4d7e1d8c2c6d5d1d5d1c4c1d7c6d6d7c9c9c8e2d9d5e5b9c5c5c5c4c4d5d6e4b9c5e4c5c5b9c4c4c1c1e2c5c5d7e2e4c4e4c5c1c4f2b9d7c5b9b9c5b9c9e7d3b9e4e4f2e2e2e3d7e5d7d9e6c1d4c5c2c1c2c0f5e6c4c5b9c6c1d8c2d6e6c2c3d4d7e1d8c2c6d5d1d5d1c4c1d7c6d6d7c9c9c8e2d9d5e5b9c5c5c5c4c4d5d6e4b9c5e4c5c5b9c4c4c1c1e2c5c5d7e2e4c4e4c5c1c4f2b9d7c5b9b9c5b9c9e7d3b9e4e4f2e2e2e3d7e5d7d9e6c1d4c5c2c1c2c0f5e6c4c5b9c6c1d8c2d6e6c2c3d4d7e1d8c2c6d5d1d5d1c4c1d7c6d6d7c9c9c8e2d9d5e5b9c5c5c5c4c4d5d6e4b9c5e4c5c5b9c4c4c1c1e2c5c5d7e2e4c4e4c5c1c4f2b9d7c5b9b9c5f7f0e9g1b2", -"a2a7a6a7b3c5b9c2c2c1c1c2c2e3d0c3c8d8c2c2c4d5d5d1d5d4c1c5d7c9c5c8d6e7d9b9c4d0d4c2c5c4c2c5c1b9e4b9c9d7e3c5c6c6c1c1d1c1c5d7d6c7e3e6c6c5c1c5b9c5d2d7d7c5d7c5d7e7d2f3b9b9e2f2d7c2c1c4d7f2e5f6e6c5c6c2c0c4f5c1d8c5b9c2c2c1c1c2c2e3d0c3c8d8c2c2c4d5d5d1d5d4c1c5d7c9c5c8d6e7d9b9c4d0d4c2c5c4c2c5c1b9e4b9c9d7e3c5c6c6c1c1d1c1c5d7d6c7e3e6c6c5c1c5b9c5d2d7d7c5d7c5d7e7d2f3b9b9e2f2d7c2c1c4d7f2e5f6e6c5c6c2c0c4f5c1d8c5b9c2c2c1c1c2c2e3d0c3c8d8c2c2c4d5d5d1d5d4c1c5d7c9c5c8d6e7d9b9c4d0d4c2c5c4c2c5c1b9e4b9c9d7e3c5c6c6c1c1d1c1c5d7d6c7e3e6c6c5c1c5b9c5d2d7d7c5d7c5d7e7d2f3b9b9e2f2d7c2c1c4d7f2e5f6e6c5c6c2c0c4f5c1d8c5b9c2c2c1c1c2c2e3d0c3c8d8c2c2c4d5d5d1d5d4c1c5d7c9c5c8d6e7d9b9c4d0d4c2c5c4c2c5c1b9e4b9c9d7e3c5c6c6c1c1d1c1c5d7d6c7e3e6c6c5c1c5b9c5d2d7d7c5d7b8b6e9g1b2", -"a2a6a7a9a5c5b9c6c6d8c1c1d7e5e6d5c4d8c6c6d5d4d1d5d1d7c5c1e3c5c1c2c8e7e4b9e4e0d5d8c5b9e4b9f2b9c5e2d7d7c5e6e6e6c1c6c2e3c5e3d6c9d6c6c1c4c4c1c1b9d7e2c5d7c5d7e7e4b9e2b9d2e3c1c2c6d7d0d9e5d1c3c5c2d7c6c0c3c4c2e0c5b9c6c6d8c1c1d7e5e6d5c4d8c6c6d5d4d1d5d1d7c5c1e3c5c1c2c8e7e4b9e4e0d5d8c5b9e4b9f2b9c5e2d7d7c5e6e6e6c1c6c2e3c5e3d6c9d6c6c1c4c4c1c1b9d7e2c5d7c5d7e7e4b9e2b9d2e3c1c2c6d7d0d9e5d1c3c5c2d7c6c0c3c4c2e0c5b9c6c6d8c1c1d7e5e6d5c4d8c6c6d5d4d1d5d1d7c5c1e3c5c1c2c8e7e4b9e4e0d5d8c5b9e4b9f2b9c5e2d7d7c5e6e6e6c1c6c2e3c5e3d6c9d6c6c1c4c4c1c1b9d7e2c5d7c5d7e7e4b9e2b9d2e3c1c2c6d7d0d9e5d1c3c5c2d7c6c0c3c4c2e0c5b9c6c6d8c1c1d7e5e6d5c4d8c6c6d5d4d1d5d1d7c5c1e3c5c1c2c8e7e4b9e4e0d5d8c5b9e4b9f2b9c5e2d7d7c5e6e6e6c1c6c2e3c5e3d6c9d6c6c1c4c4c1c1b9d7e2c5d7c5b6e9f0f0b2", -"a2a6a7a9a5d5c4d9c2e6c1c2c5e5c2d1c1d5c1d5d5d1c4c4c1d7c1c9c8e3e5e6c6c2c9d9c5d8d5f5e4c2e4b9e4c5d7f2d7d7c5c1c1c1c1c2d7e3d7e3d6e7b9c2c2c1c1c4b9b9c4e4d7c5c5c9b9c5b9d3f2c5c2d7c2b9d7d0c1e5c0c4d7e5d7c6e5g2d1c2d5d5c4d9c2e6c1c2c5e5c2d1c1d5c1d5d5d1c4c4c1d7c1c9c8e3e5e6c6c2c9d9c5d8d5f5e4c2e4b9e4c5d7f2d7d7c5c1c1c1c1c2d7e3d7e3d6e7b9c2c2c1c1c4b9b9c4e4d7c5c5c9b9c5b9d3f2c5c2d7c2b9d7d0c1e5c0c4d7e5d7c6e5g2d1c2d5d5c4d9c2e6c1c2c5e5c2d1c1d5c1d5d5d1c4c4c1d7c1c9c8e3e5e6c6c2c9d9c5d8d5f5e4c2e4b9e4c5d7f2d7d7c5c1c1c1c1c2d7e3d7e3d6e7b9c2c2c1c1c4b9b9c4e4d7c5c5c9b9c5b9d3f2c5c2d7c2b9d7d0c1e5c0c4d7e5d7c6e5g2d1c2d5d5c4d9c2e6c1c2c5e5c2d1c1d5c1d5d5d1c4c4c1d7c1c9c8e3e5e6c6c2c9d9c5d8d5f5e4c2e4b9e4c5d7f2d7d7c5c1c1c1c1c2d7e3d7e3d6e7b9c2c2c1c1c4b9b9c4e4d7c5c5f0f0b6f0b2", -"a2a7a7a7b3c4d5c2d1d7e6d7c4c2e0d5c1c6c2c4c2c1c1d5d7d7c2d7c5f6g3c1c0c4d9b9f5e5c4d5b9b9d5b9e4e4e4b9c2e3c6c1c1c4d0c2c6e3c9c9c8c9b9c8d7c4c1c4e2c4b9c5e4c5c2b9d7b9d3d2g8d6c2c2e4e2d7d0c6e5e2c1c2c1c1c6c1d1d1c4c1c4d5c2d1d7e6d7c4c2e0d5c1c6c2c4c2c1c1d5d7d7c2d7c5f6g3c1c0c4d9b9f5e5c4d5b9b9d5b9e4e4e4b9c2e3c6c1c1c4d0c2c6e3c9c9c8c9b9c8d7c4c1c4e2c4b9c5e4c5c2b9d7b9d3d2g8d6c2c2e4e2d7d0c6e5e2c1c2c1c1c6c1d1d1c4c1c4d5c2d1d7e6d7c4c2e0d5c1c6c2c4c2c1c1d5d7d7c2d7c5f6g3c1c0c4d9b9f5e5c4d5b9b9d5b9e4e4e4b9c2e3c6c1c1c4d0c2c6e3c9c9c8c9b9c8d7c4c1c4e2c4b9c5e4c5c2b9d7b9d3d2g8d6c2c2e4e2d7d0c6e5e2c1c2c1c1c6c1d1d1c4c1c4d5c2d1d7e6d7c4c2e0d5c1c6c2c4c2c1c1d5d7d7c2d7c5f6g3c1c0c4d9b9f5e5c4d5b9b9d5b9e4e4e4b9c2e3c6c1c1c4d0c2c6e3c9c9c8c9b9c8d7c4c1c4e2c4b9c5e4c5c2f0b6f0e9b2", -"a2a7a6a6a5c1c6d1d5d0d1e0c2d7d7c1c5c9d9g9h0b0d2d5d5d8c6d5d7d1c2c6c1c4c2c1c5c1d5e5c5e4c2c2c2e4b9c5c6c6c1d1c2b1b0h1a5a7g6f2d6c7d6d6d6c1c5c1c4c5c5d7c5d7c5d7e4b9g6e4e2b9c5h2b1h2h2h2h2h2h2h2h2f4e4d1c0d1d4c3d5c1c6d1d5d0d1e0c2d7d7c1c5c9d9c5c5c1c0d5d5d8c6d5d7d1c2c6c1c4c2c1c5c1d5e5c5e4c2c2c2e4b9c5c6c6c1d1d1g9h2h2c3d9g6f2d6c7d6d6d6c1c5c1c4c5c5d7c5d7c5d7e4b9g6e4e2b9c5e2e2e4d0c1c6e5h2h2h2g6d4d1c0d1d4c3d5c1c6d1d5d0d1e0c2d7d7c1c5c9d9c5c5c1c0d5d5d8c6d5d7d1c2c6c1c4c2c1c5c1d5e5c5e4c2c2c2e4b9c5c6c6c1d1d1d4c5c5c0d9g6f2d6c7d6d6d6c1c5c1c4c5c5d7c5d7c5d7e4b9g6e4e2b9c5e2e2e4d0g9h2h2d7c2c1e5c4d1c0d1d4c3d5c1c6d1d5d0d1e0c2d7d7c1c5c9d9c5c5c1c0d5d5d8c6d5d7d1c2c6c1c4c2c1c5c1d5e5c5e4c2c2c2e4b9c5c6c6c1d1d1d4c5c5c0d9g6f2d6c7d6d6d6c1c5c1c4c5c5d7c5d7c5b6e9f0g1b2", -"a2a8a6a7a5c2c2e1d5e6d5f1c2c1c5c5b9c2c9b1h3a5b0b9e1e1c1c2c4d5c1c5c4c1c3d5c4c2f6d5b9e5c5b9c5b9b9c4e6e6c1d2b7h4b7a5h5h5b0e4d7d7d6d6c8c1c4c4c5c5d7e4c5c9b9b9d7d9e2f9e4e4d9b3h3b7b7h3b7b7h3b7b7b7h3b3b1f4c3e5e0c2c2e1d5e6d5f1c2c1c5c5b9c2c9b9c5c2c4f6e1e1c1c2c4d5c1c5c4c1c3d5c4c2f6d5b9e5c5b9c5b9b9c4e6e6c1d4d5a5h5a5h6g6f3e4d7d7d6d6c8c1c4c4c5c5d7e4c5c9b9b9d7d9e2f9e4e4b9c5e4b9e5e5c5h2h1b7b7h7d6c0c0c5c3e5e0c2c2e1d5e6d5f1c2c1c5c5b9c2c9b9c5c2c4f6e1e1c1c2c4d5c1c5c4c1c3d5c4c2f6d5b9e5c5b9c5b9b9c4e6e6c1d4d1c1d7c6c1f3f3e4d7d7d6d6c8c1c4c4c5c5d7e4c5c9b9b9d7d9e2f9e4e4b9c5e4b9e5h1h3b7h8d1e5c1d4c0c0c5c3e5e0c2c2e1d5e6d5f1c2c1c5c5b9c2c9b9c5c2c4f6e1e1c1c2c4d5c1c5c4c1c3d5c4c2f6d5b9e5c5b9c5b9b9c4e6e6c1d4d1c1d7c6c1f3f3e4d7d7d6d6c8c1c4c4c5c5d7e4c5c9b9f0b6f0g1b2", -"a2a7a6a7a5e6c1f1d0c1d1e0d7c2c1c5c1d7c9h0a5h5h5h9g5e1c0c5d7c1f1d5d1e1d8c3c2c4d5d5b9c4d9c6c2b9c4b9e6c6c1h0h4h5h5h5h5h5i0f0e6d0d7e7c9c4c4c5c1e4c5c5e4c4d7c4e2b9g6d2d3b9d2h1h5h5h5h5h5h5h5h5h5h5h5h5h5b7a8d7d5c6c1f1d0c1d1e0d7c2c1c5c1d7c9e4c4c8c4d8e1d8e6d7d7c1f1d5d1e1d8c3c2c4d5d5b9c4d9c6c2b9c4b9e6c6c1c4c1h1h5i0h8g7f2b9c8e3c8e7c9c4c4c5c1e4c5c5e4c4d7c4e2b9g6d2d3b9e4b9e2b9e5c4f3b7b7h5h5h5g8e1d4c4d5c4d5c6c1f1d0c1d1e0d7c2c1c5c1d7c9e4c4c8c4d8e1d8e6d7d7c1f1d5d1e1d8c3c2c4d5d5b9c4d9c6c2b9c4b9e6c6c1c4c1e3c5c1c6f3d2e4c7e3c8e7c9c4c4c5c1e4c5c5e4c4d7c4e2b9g6d2d3b9e4b9e2b9d2h1h5h5b0i1c3c4d4d1c0c4c3d4d5c6c1f1d0c1d1e0d7c2c1c5c1d7c9e4c4c8c4d8e1d8e6d7d7c1f1d5d1e1d8c3c2c4d5d5b9c4d9c6c2b9c4b9e6c6c1c4c1e3c5c1c6f3d2e4c7e3c8e7c9c4c4c5c1e4c5c5e4c4d7f8g1f0g1b2", -"a2a7a7a7b3c2c1e0e6c6c1d5c2d7b9c1d5c5d7b7a5h5h5i2i3f6e5d7d2e3f1f6c4d8d8g3c1b9f5d0c4d5c2f2b9b9c0e2c6c1d2h1h5h5i0h8c9g2e1i2e1f5d4c5c9c5b9c4c5b9c0c5d3c8b9c0e2e4d2f9e4d9f9h1h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5i0d2d0e5e0e6c6c1d5c2d7b9c1d5c5d7e4b9d5e5d4d5c9c9c9f9e3f1f6c4d8d8g3c1b9f5d0c4d5c2f2b9b9c0e2c6c1d4d0f9h1h5h5c9g1e6e6e6c2e3c7c9c5b9c4c5b9c0c5d3c8b9c0e2e4d2f9e4b9c5c4b9c2c1c4b1h1h5h5h5h5h6h9e0d8d5d4c4c2c1e0e6c6c1d5c2d7b9c1d5c5d7e4b9d5e5d4d5c9c9c9f9e3f1f6c4d8d8g3c1b9f5d0c4d5c2f2b9b9c0e2c6c1d4c1c6e3d0c2g6d2g6b9c7d7e3c7c9c5b9c4c5b9c0c5d3c8b9c0e2e4d2f9e4b9c5c4b9c2d2h2h5h5h8i4g2e1e0f5c0d1d1c4c4c2c1e0e6c6c1d5c2d7b9c1d5c5d7e4b9d6e5d4d5c9c9c9f9e3f1f6c4d8d8g3c1b9f5d0c4d5c2f2b9b9c0e2c6c1d4c1c6e3d0c2g6d2g6b9c7d7e3c7c9c5b9c4c5b9c0c5d3c8b9b8e9f0g1b2", -"a2a7a7a6b3c2d7c4d7c2d1c5d7d7c5d5e5d7f4h1h5h5h8i2i3g7g7e1e7c6c4e5c1d5d8e1f5c2c2d5d5c4c2c2c2d7e4c2e5d4h2h4h5h5c9i2b5i5g1g1g5i6f1d4d7c4c4c2c5c0e2b9b9b9c5e2b9c5d7d2e2c2h2h4h5h5g2i2i2i2i2i2i2i5e1g8h5h5h5h5b0c2c0d5c5c2d1c5d7d7c5d5e5d7b9c9f6d4d8e5e3e7c6e5d3c2c4e5c1d5d8e1f5c2c2d5d5c4c2c2c2d7e4c2e5d4d8c1h2h3h5h5i3i7e1e1d8c0c6c8c9c4c4c2c5c0e2b9b9b9c5e2b9c5d7f3e2c2b9c5c1c2c3f4h1a5h5i0h8h5b0a0g5i8d8e0c4c2d7c4d7c2d1c5d7d7c5d5e5d7b9c9f6d4d8e5e3e7c6e5d3c2c4e5c1d5d8e1f5c2c2d5d5c4c2c2c2d7e4c2e5d4d8c1c5c1e3e4d2d2g6b9d7e3d7c8c9c4c4c2c5c0e2b9b9b9c5e2b9c5d7f3e2c2b9c5c1c2c3g8h8c9i3a0i6g5i3d8f6c0c1f5c4c2d7c4d7c2d1c5d7d7c5d5e5d7b9h2a5a8c2e5e3e7c6e5d3c2c4e5c1d5d8e1f5c2c2d5d5c4c2c2c2d7e4c2e5d4d8c1c5c1e3e4d2d2g6b9d7e3d7c8c9c4c4c2c5c0e2b9b9b9c5e9f7b6b6b2", -"a2a7a9a6a5c4e6d1c2c2c1c5c9c9d5b9c6c5g9h4h5h5g8a0i1i7i9f1d4e6d1e5c4c0c0d5d5g2c4g3e5e0d9c5c5c2b9c5d1f5a6b7h5h5g0j0i6i1i5g1g4h9g5e1e5c4c5c5c5c5e4d7d3c8b9e4b9c5d9b9d3d6b1b7h5h5i9f7i7j0g4g4i5i5g0g0b8h6h5h5h5h8i6e0c0e6c1c5c9c9d5b9c6d6d9b9d5d1c0d0c9d6c1d6c9e3e5e5c4c0c0d5d5g2c4g3e5e0d9c5c5c2b9c5d4d5g3c5h2h3h5h5g0i1i9a2g7e0c1e3c9c4c5c5c5c5e4d7d3c8b9e4b9c5d9b9d3d7c6d7c1e5c1b0h4h5h5c9g8h5h5a0h9i9g7f1d5c4e6d1c2c2c1c5c9c9d5b9c6d6d9b9d5d1c0d0c9d6c1d6c9e3e5e5c4c0c0d5d5g2c4g3e5e0d9c5c5c2b9c5d4g3d5c6c6c4d3d2f4f3b9c9c7e3e3c8c9c4c5c5c5c5e4d7d3c8b9e4b9c5d9b9d3d7c6d7c1e5c1d1e1i7i5i5j1j1a2g7d8c4c6d5c4c4e6d1c2c2c1c5c9c9d5b9c6c7d9b7h5i0b0d8c9d6c1d6c9e3e5e5c4c0c0d5d5g2c4g3e5e0d9c5c5c2b9c5d4g3d5c6c6c4d3d2f4f3b9c9c7e3e3c8c9c4c5c5c5c5e4d7d3c8b9f0f0b8f0b2", -"a2a8a9a6b3c1c4e6c5c1c5e4c9e6c1c1c9d9h2h3h5h5c9a4f7f0j0g5e1c4d8c1e6e6e5e6c3d5d8d5c4d5c5b9d5c2e2c2c4c1a5a5h5h8i4a2j1e8j2b4g0e9j1i6f5e5d7d9c4c5c5d9b9d7e4d7b9b9c9c8e7c9b0b7h5h5a4g1f0j2b4j2b4j3g0g0g0j3g8h5h5h5c9g7d8d5e6e4c9e6c1c1c9d9b9d6c9d4c4g2d5c5d6c5c8c6d5e5e6e6e5e6c3d5d8d5c4d5c5b9d5c2e2c2c4e6c7c8h0b7h5h5i2i7i5g4i9g7f5c1e3c6c8d9c4c5c5d9b9d7e4d7b9b9c9c8e7c9c5e6e5c4g9h1a5h5b0i2g9h5h5i9b8h9g5i3g2c0d4c6c5c1c5e4c9e6c1c1c9d9b9d6c9d4c4g2d5c5d6c5c8c6d5e5e6e6e5e6c3d5d8d5c4d5c5b9d5c2e2c2c4e6d6d7c1c6d2d2g6c9d7e3c5c5c6c5e3c6c8d9c4c5c5d9b9d7e4d7b9b9c9c8e7c9c5e6e5c4c6c1e5f6g7i9i5g1i7g5e1c6c2g3c1c1c4e6c5c1c5e4c9e6c1c1c9d9f4h1h5h5g8a0d8e5c5c5c8c6d5e5e6e6e5e6c3d5d8d5c4d5c5b9d5c2e2c2c4e6d6d7c1c6d2d2g6c9d7e3c5c5c6c5e3c6c8d9c4c5c5d9b9d7e4b6f0f0f0b2", -"a2a7a7a6b3c1c0c2d7e6c5d7d7c6c6c1c9d7a7b7h5h5i9b4e8j2g1i1f1e0f5c6c2e5e6d1c9d5c4f5f6b9e5e2c1c2e4c5c1c8h1h5h5h8a0i9f0b4b4f8f0i5i1i6d8c6d9c9c5d7b9d9d9b9b9e2e4c5c5c9d6c9h1h5h5i0i2i5g0j4j4j2e8g0g0g0g0g0i9b0h5h5b0g0i3e1c4c5d7c6c6c1c9d7d3b9e6d5f5f5f6c7d7c6c8c3f5c6c2e5e6d1c9d5c4f5f6b9e5e2c1c2e4c5c1c8f2e3b3a5h5h8i2i7b8b8j0i6e0c0c2c8d9c9c5d7b9d9d9b9b9e2e4c5c5c9d6c9e3e6c4c9a5b7h5h5i3b2h3h5h5c9a4b8h9a2e1d4c0c2d7e6c5d7d7c6c6c1c9d7d3b9e6d5f5f5f6c7d7c6c8c3f5c6c2e5e6d1c9d5c4f5f6b9e5e2c1c2e4c5c1c8f2e3d0d7f3g6b9c2e3c2e6c6e6c6c2c8d9c9c5d7b9d9d9b9b9e2e4c5c5c9d6c9e3e6c0c6e5c4d0d5f1g5h9g1j0i9f1f6c6d8c1c1c0c2d7e6c5d7d7c6c6c1c9c2g9h4h5h5g2b8i8f5d4d1c8c3f5c6c2e5e6d1c9d5c4f5f6b9e5e2c1c2e4c5c1c8f2e3d0d7f3g6b9c2e3c2e6c6e6c6c2c8d9c9c5d7b9d9d9b9b9e9f0b8b8b2", -"a2a9a8a6b3c6c4c8d7c2c2c5d7d7c5c0f2c9h0b7h5h5a4b8g0b4f7i8f3f4f5d5d9h2b0h0h0b0h2d4c4c0c5b9c3e4f9f9f9h2h1h5h5c9f0e5i9j4f8g4j1g5i6i8c8h2b0b0a5h0b1f9d7e7c6c2b9d7c5e2c5f9h1h5h5h8i2j0b5j4b5g1j0i7h9h9h9i7i7b1h5h5h5i5i9i6d8d1c5d7c5c0g9a6h0a5a8b0h2e5d4c9c7c2e3c3d5d5d4c2c6d7g6h2a7b0a5b0h2f4d4e4c5c1c5d9f2b9h1h5h5h6a4i5g0b5i5g5e0f9f9f9f3e6b9b9c0c7c2b9c6c2b9d7c5e2c5d3d7d4e5h2h1h5h5h8i2i7a6h5h5h8b2g0i5i1e1c0e5d7d7c2c2c5h2a6b0h0h0h0a6d3d5g2c1c3f6c9c7c2e3c3e6h2b0b0h0h0b0h2e5d8c4c0c5b9c3e4c5c1c5d9f4h2b0h0a5h0b1f9c5d0e6c6c6c1e6c5d9e6b9b9c0g9b1h0a5b0a6g9e3e2c5d3d7d4e5d6f9f9d2c4d8i8g5i7j1g5e1g9a7b0a5b0a6h2f2c2c2c5d7d7d9f4g9f9a6h3h5h5i9g5e6f1f1g2c1c3d5d5d4f4b1b0h0b0b0h2f4c0c5b9c3e4c5c1c5d9f2e3d2b1h0h0h0h0b0g9e6c6c6c1e6c5d9e6b9b9c0c7c2b9c6f0f0b6b6b2", -"a2a8b0a6b3c6c6f5c2d0c5c5d9c0b9c0d9e7h1h5h5b0i2g1b5b4g1b1h4h3g8h2b7h4b7a5a5a5a5b7d2c5c0d7c5d2h1h3h3h4b7h5h5c9f9h3f9j1e9i9i3f1c2a6h1h4b7a5a5h5a5a5h5c9c2c2e4c9b9d7e4g9h4h5h5c9a4g4b4b4g1i1i6g7g7i3i3g7f1f9a5h5h5g2b8j1i3f5c7c3h2b7h1h3a5a5h5a5a5h5g9d7c8d7d4d1c4e5c1c9c7b1h1h4b7a5a5h5a5b7h2c4e0e0d6d9c7f9h4h5h5g2j3i5b4b5j0e6h0h1h4h7g8d7c4c5b9c6c2c6c2c2e4c9b9d7c9d3c9b9e4b7b7h5h5i9a0i9g9a5h5h5i4j3g4i7g7c3d0f5c2e6g9b3h1h3a5a5h5a5a5a5b1c3f6c3d4d7c8d7g2b1h1h1b7a5a5a5a5a5b7g9g3c5c0d7c5c4e0e0f4a8h1h4b7a5a5h5a5a5a8c7c6e6e6c1c1c4c1c1c4f9a5h1h3a5a5h5a5a5h5f9c9d3c9b9c0f9h1h3g9b9d5d5f1g7i6f9b7h1h3a5a5h5a5a5b7g9c5c5d9c3h2h1h4h3h4a5h5h5i3b1h3d7i3f1e0c3e5f4b0h1h3b7a5a5a5a5b7b1c0d7c5c4e0e0d6d9g6b0h1h4b7a5a5a5a5a5b7f4e6c1c1c4c1c1c4c5b9c6e3c6e6f0f0f7f0b2", -"a2a7b0a6b3d7c0e1c3c3d7b9c4d8d5e2b9f9h1h5h5h8i4g1b4b5g4a7a5h5h5b1h5h5h5h5h5h5h5h5i0d3d6e6c5f9h4h5h5h5h5h5h5h5h5h5h5g2i5i6e0d2b7h4a5h5h5h5h5h5h5h5h5b0e2e6e6d6c9c9c9h2h3h5h5e1g0f7j3g0i5g5e1f5d5d8f5c3c4h2b7i0h5c9a4g1i9e1d8b1h1h3h5h5h5h5h5h5h5h5i0h7c0b9d1c0c1e6e6f4h0h4b7h5h5h5h5h5h5h5h5h7c3e5d6c9e3h2h4h5h5i9b8g1j3f8f3b7h4h5h5h5h6e1g2d9c5c8e6d7c8c2c5d6c9c9c9e7c2e5b1h4h5h5h6i2i7j0d9b7h5h5i5j3f7i5g7c3d1e1c3b1h1h3h5h5h5h5h5h5h5h5h5h7d8c3d1c7e3d2h0h1b7h5h5h5h5h5h5h5h5i0g9e6c9c5c5c4c1f4b7h4a5h5h5h5h5h5h5h5h5b0b9e5c1c0c6d7d7c1h2h1h3h5h5h5h5h5h5h5h5b0h6d7e6e5c4g9h4h5h5g8d8d4d5d8g9h1h3h5h5h5h5h5h5h5h5i0h6c9d4d8h2h5h5h5h5h5h5h5h5h5h5h5i9g7f1c3g9h1h4a5h5h5h5h5h5h5h5h5h7e5e6c4c1e5d9f9b7h1a5h5h5h5h5h5h5h5h5i0g8f6e6d7d7c1c4e4c5c8e6d7c8b8b6f0f0b2", -"a2a8b0a6b3d7c1e0c1c3c5c4e5f5c4e3e4g9h4h5h5c9a4f7b5g0j0b7a5h5h8h6h5h5h8c9c9h8b0h5h5b0i3f6c0e6g8h5h5h5h5h5h5h5h5h5h5i9f8i6e4h1h4h5h5h5b0h6c9c9h8h5h5i0b0c3d4d6e6c2b9b0b7h5h5i9e9b6j4e8i7g7d5d0d0e5e5d7d3f9b7h5h5c9a4g0j0g5b1h1a5h5h5h5h8c9c9c9b0h5h5h5g8d4g2d1c1e6c7a5h4a5h5h5b0h8c9c9h8h5h5h5c9e6c2d7e3b1b7h5h5a4j0f0f0h2h1h3i0h5i0i9i2j1c3c6d7c2e6c1c6c5c5b9e6e3c9c9c7f9h1a5h5b0g0b5i1b6a1b7h5h5g2j4f7g4i6d5c0e0f9h1a5h5h5i0h8c9c9c9b0h5h5h5e5e1e3c2d7h2h1h5h5h5b0h6c9c9c9b0h5h5h5f1d5c4e6c2d3h1h4h5h5h5b0h6c9c9h8h5h5i0b0d5c3f6e6d7c2h2h1b7h5h5h5h8c9c9h6b0h5h5b0e0e5d1e6h2h3h5h5g0g5d5c3f4h1b7h5h5i0h8c9c9c9b0h5h5i0g5d8e1c4h8h5h5h5h5h5h5h5h5h5h5i2j1g7f4h1b7h5h5i0b0h8c9h6h8h5h5h5h6d5e5d8e4c9h0h4h5h5h5b0c9c9c9h6h5h5i0b0i6f6c6c6c7c2b9b9c2e6c1c6b6b8f0b8b2", -"a2b0b0a6b3e3e6g2e6c1e5e4c4f5c2f2c2h2h3h5h5e1j3b8b4b6i7h1h5h5h5h5h8h9i4j3f0g0i3h8h5h5i9e1e1g7c0e1i2i2h8h5h8i2i2i2i2i2b6g7a5h3h5h5h5c9i2i4g0e9b4g5i0h5i0c9i8d1e6c8c9a5a5h5h5i2e9e8j4e8j1e1d5c1e6e5c1f2f3h2h3h5h5c9a0b5f0f9h1a5h5h5h8h9i4a0j0i5j3h6h5h5b0i9e1g3e6e6b1h4h5h5h5h6i2i2a0i5b6f1h5h5i0i9e0d4c1b0a5h5b0i4i7i6b0h1b7h5h5h8b2i4g5f1f1g2d5c1c4d7c8e5c5c7d7d6c9c7c4b0h3h5h5c9i4i9i5g0j4a5h5h5h6a0b8f7i6d8d4g3a7h3h5h5h8a0i2b4f0b6b8h6h5h5h8i5e0c1e3b7b7h5h5g8b2i4g0g4g1j1h8h5h5c9g5f6g2d8a5h3h5h5h5c9i2i4g0b8j2g5i0h5i0c9i8e0c0c2d2b7b7h5h5b0i5b2j3b8g0h9h8i0h5c9i3e0f5b0b7h5h5i2i6e1e1b0h3h5h5h8a4i2b4f7f8f0h8i0h5g2i3g7c3d6i1i2i2h5h5c9i2i2i2i2i2i7g7a5h3h5h5b0g2i2i2a0b8j3c9i0h5h5g5g5f5d9f4h1a5h5h5e1i2a4f7b8g0g7i0h5h5i9i8g2c1c8b9e2d7c8e5c7c8f8b6f0f0b2", -"a2b0b0b0b3c8c5c5d7c2c5e5d5c4c4d9c8h0b7h5h5i9f7e9b4e8e5h1h5h5h5h8a0b2i7a2i9h9f7h5h5h5c9g4g7e1g3e2e6h1h5h5h6b2f8b4j4j2f0g9h1h5h5h5e1i2g1i6i1i7i5b8h2h5h5b0g0e1c3c2d7h1h5h5h8i2j0b5b4g1i9d8e6d0c6c4e6f2f2b1b7h5h5c9a0g0a2b7b7h5h5h8a4a0i1i1i9h9g4e1b0h5h5g2a2f5d6f4h1b7h5h5e1i2g0a2h9j1i5e4b0h5h5i9a2f1f5h1a5h5h8i4f4h1h4h5h5h5c9i2j3g5g5i9i1i6g7e0e1c8c5c3e5d3c9c9d6d7g9h1a5h5b0a4g1i7f0j2j2b1h5h5b0a4f0j0a2e1e5e3h1a5h5h5a4a4g5a2i7h9b8d7h5h5h8a4i6i8f4h1h5h5h8i4g0g5i1h9g4j0g9h5h5c9f8g5e1h2h1h5h5h5e1i2g1i9j1j0g4b8h2h5h5b0f8i3e0c3h0h4h5h5h8a4i4g5i9i5i5i5a8h5h5h8f8i6e1b7a5h5h8i2a2a2g3a7h5h5i0a0a0g7a2i7i5g1h4h5h5c9g0g5i8e6c1g9h4h5h5e1a0f8b4j3g0g0b1h4h5h5i0g0i4j0g5j1i5b8g4h7h5h5h6j1i8c0h2h3h5h5c9i2h9g5j1i5g1a2h8h5h5i9j0i3e0c5e3b9c2c1d8d6c5g0f8e9f7b2", -"a2b0b0b0b7d1e3d9c2d6e4c4c4b9b9d9b9a5a5h5h5i2g4b8j3f0f4h3h5h5b0g0b2b8i5g4f7e8g0h4h5h5c9a0j0i6d8c6f4h4h5h5g2b2j3j4j4j4a2h1b7h5h5g2i2h9i9i5g1g0b4j3f4b0h5h5g0i9g7g3f9h1h5h5h8b2g4j2b5g4a2d5d7e6e6e5c1f2g6h0b7h5h5i9a0g0b1b7h5h5b0a4a0g5h9g1g1f8g0b5h3i0h5g8g0i3g3a5h3h5h5h8i2i7i9i7g1g0j2a2a8h5h5i9b8i9d9h1h5h5c9h9h1b7h5i0b0f7i2g4i6i7i5f7g4i7g5i8f1e6d6d8e2c8d6c2d6g6a5h3h5h5e1i4a2i5j2b5g1f9a5h5h5a4f7g1i9i6d1c9h1h5h5h8i2i6j1i5b6j2b4j2e5c9e1b2h9a2d2h3h5h5c9a0i9i5g1e8b5j2f8g8c9i9a0i7f5h1b7h5h5g2i2i5i1i5b6b5b4b4f4h5i0h5g0i1g7f9h1a5h5h5h9a0i1j1i5b5f8b5g9b0h5h8b2j1i8h1h5h5h6a4i7h9j1e1h8h8g2i4g7i9g4g0b5g0h1h5h5c9a0i1i3g3e5h2h3h5h5i5a0j3j3j4b4a2h1a5h5h5i9i4g5i9i5b6b5b5g0b1i0h5h8a4i9e1h2b7h5h5i9g1i9i5b8b5b4b5i1c9c9g0g0j1g7f5e3c2e3e5d8c5d6j2e9b6f0b2", -"a2b0b0b0b7d1d7d9c8b9b9e5e5e4b9f3d9h1h5h5h8i2i7e8g0g1g9h3h5h5c9i4b5j3j3g0b5b5b8h1h5h5c9a4e9j1i3e1h2h3h5h5i9a4j4j4j4j4g9h4h5h5h8i2i5j1g1b5b4b4g0f0g3b7h5h5g2g1i1g7g9h3h5i0c9a0g4j3g0i5i6c8e3e6d0c4c1d2f4h1a5h5h5i5f0g4h1a5h5h5i3b2g5h9e8b4g0e8f0g1b1h5h5i0a4j1e6h1h5h5b0b2b4a2i5f0j2j2e8g0i3h8h8i5j3j0e4h4h5h5e1f4a5h5i0h8a4b2i9i9h9f7g0b4b6j0g5i8g2e6c7d8c2c8c1d7c6h2h4h5h5h8i2i5i7e8b4f0j0f3b7h5h5i3b6f0i9i6d4c8b7h5h5b0h9i6g1f8j2g0f8f7h9g0a0j4e9h9e5h3h5i0h8a2g4g0j4j2f8b6g1i5a0a0b4g0h2h3h5h5h8i2i5i1g4b5j4b4g0g0d8b7h5h5g2b8i9b1h3h5h5c9i2i9h9f7b5a0j2e8b8h6h8c9b2g4e6h4h5h5c9j3i5g1g1i9i3b5b4i7a2g4g0j4g0e1h1h5h5c9a4g4i1f1g3b0b7h5h5i2j4b4j3b4g0g9h4h5h5c9i2i7h9g4g0j3j2f8g1b1h5h5h5b2i5i9g9b7h5h5e5i6g4g0j3j4g0b6g1f7a0a4g0g1i1i6f6c1d7c1c4c2c7j2f0b6b8b2", -"a2b0b0b0b3d0b9c9c6d9e4e5d0c5b9g6g9h1h5h5h8b2h9g0j2j0a7b7h5h5g0j3b8a0j4j2b6g1e5h1h5h5c9a4f8g1i9i8b1b7h5h5a4j3j3j4b4f0h0b7h5h5i9a4i9g1g0j3j2b6i5j0e6h4h5h5c9a0g4i9h2h3h5h5i3g0f0j4e8h9i6c4e3c8d0e5e3g6h2h1h5h5b0i4b6d9h1h5h5h8i2i1i1f7j4j4b6j0j1i9a6a5h5h5i2g1h2b3h5h5c9b2g5j0f8j2j2b6g1h9i1h9a4b2j3b6g9h3h5h5c9b0h5h5g2i2a4i9j1g4b8b4j2e8i5i9i3g7d5c7c7d8c2d6c1c5d2b7b7h5h5i9a0i9g4b4b4g1i9e5h3h5h5c9j3b6i5g5d5c8g9h5h5i0i0h5b1f4i9g4j0i1i3i3a2h9g1g4i1h2h5h5h5b0h5h2c2h9j0j1i9i6a2i1g4b8h0b7h5h5i9a0i9g4b5j4j3b8g4i7e6h4h5h5c9a0j1h1a5h5h5a4g1j0f0g0b4j3e9i7j1i9g0a0a0b8f4h3h5h5i9g0f7b5f0i1i3g9b1b0h1h1h1h1h1h1h3h5h5i9a0e8g4a2d8a5a5h5h8i4f0b4b4b8g1h0b7h5h5b8g7g9f4f4f4f4f4g9g9h0a5h5b0i4b8i5i9h5h5h5h5b0h0h2g3g0g4i7i9i9i9j0i5b8j0g5e1e5e6d8c1d6c7j2b6f0e8b2", -"a2h0a6a6b3e6b9c7c8d3b9c1e4b9c0e5h2h3h5i0c9j4j0b4f8h9b3a5i0b0i2g4e8a0j4e8j0i9f4h3h5h5i3a0g0f8i7i6b0a5h5i0i2b8b5b4g0e1h1h5h5b0i2i5i5g0b4b4b8i7g5a2f3h3h5h5c9a0f8j0a6b7h5h5i5f7e8j4e8i7g7d0e6c5e5c1d6f4a6b7h5i0h8i2f0b1b7h5h5e1a0i1f0j2j4b5i7a2i8f1a8a5h5h5i2f0h0b7h5h5i5f7i1b8b4g0f0j0i9i6g7i8g7i9g4b4b1b7h5h5h5h5b0i5i2a0i5i5f7b5j2j2f7j0i9i8f5e1e5c7d7d8c5d6c4c1b1h4h5i0h8i2i7j0f8j4b5h9a2e1h3h5h5h8a0b4g4a2g3e6e7g9h5h5h5h5h5a5b7h0g9e1c0e5f5i6j1j0i7g5h8h5h5i0h5h5a5h3h0f4f1g3d8g7i9f1h1h5h5b0i2h9j0g0j4j3b6h9i9i6e4h3h5h5c9a4d9h1h5i0h8i2i9f0b5b4g0f0i1i3i3e1i8i6j1f0h2b7h5h5a4g1b6j2b6e4h0h1h3a5a5h5h5h5h5h5h5h5h5g0g1b6g0h9g5h1h5h5h8a4j0j2j2g1g3h1h5h5b0c9h5h5b7h3b7h3h3h5h3h5h5h5h8i2b6b6j0g7b0h5h5h5h5i0b7h3b1d9i8f1g7g5i9j0i5i1g7d4d7d8d0c9c8j2b8f0f8b2", -"a2b0a6a6b7e6e5b9d7c6c2c5f2e2c5d7b1b7h5h5i3b8f0b4g0a2h1h5h5g8b2i5g0j4b4i5a2i6h2h3h5h5g0g0g0j2i5g5h1a5h5h8i2i5b5j2f0e6h4h5h5c9b2h9b8j3j3b8i5g5e1i8h2h3h5h5i3a0g0f0b3a5h5h5i2g1f8j4g1i1f1c4d0c5c2e5e6d2h1a5h5h5i3a0g1b1a5h5h5b2f7i5g0j2j2g1g5d8f5c3b7a5h5h8i4f7h1h5h5b0i2j1i5j3j4f0i7g5i8e0d8g2e0i3i9i5h0a5h5b0h5h5b0a4a0b5b8b5b5j3b5f7i7g5i3g3e6d8c1d6c5d8d8e5d6f9h1b7h5h5j3g7h1h1h1h1h1h1h1h1h1i0h5h5i4b4j0i1i8c6e3d7c2h8h5h5h5h5h5h5h5b7f4f2c3e1i6i9i9g5e1c9b0h5h5h5h5h5h5a5h5c1e6c3g7c2h4h5h5c9b2i1e9j3a0b8h9g5g7d8g9h4h5h5i3a4f4h3h5h5i3j3i7b5j3g0g1h9a2e1d1c3f5f5i6j1a6b7h5b0i2h9e8b4h2h1h3h5h5h5h5h5h5h5h5h5h5h5h5i2j0f0b5h9d9h1h5h5c9a0g4j2b5j0f9h4h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h8b2b8b5i5g5c3c9i0i0h5h5h5h5i0a5h7f5c3f1i3i9i9g5i3c3c5d8d0d6c2j2j2b8f0b2", -"a2a8a9a7b3d4e6c2e3c8c0c2d3c5d9d0b0b7h5h5g0g4b6j3f0e6h4h5h5c9b4g4b5j4f8i1i8e1b0b7h5h5i2g4b5j2g4d4h1h5h5c9a4i5g0j2g4f4h3h5h5i3g0g4b4j4b8i5g5e1c0e1h0b7h5h5i9b8b8j0h1h5h5h8i2i5j2b4g1a2e1e5e6c6c5e6c4b1h1h5h5i0i4f0e8a5a5h5h8i2j1f0j4g0f0j1f1c0c4g9h1h5h5h8b2g1h1h5h5h8b2j1f0j4b4j0a2e1d8f5g2d4f6d8g7a2h1h5i0h8h6h5h5h8j3j3j3a0j3g0g4i7i3e1d5e6c5f5c6c8d7d5c1d6c9b0h3h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5i5f8g0h9g7c3e6c8d4i9i9g2h8h5h5h5h5h5i0b9c0d4e0i8i8g7e1e5h9i9g8h8h5h5h5h5h5b0e6e6e1g9h3h5h5i3g0j0f8a0f8i5g5i8e0c3h0b7h5h5i9f0f4b7h5h5i9g1g4j4j3f0i7g5e1c6d7c1d1f5f5a3h1a5h5h8i4h9g0e4h1b7h5h5h5b0c9c9e1i9i9i9h8h5h8i2j0g0g0j0f9h3h5h5i9f0g1b4f0i7h2b7h5h5h8h8h8h8h8h8h8h8h8h8h8h8h8h8c9b2b8b4g1g5e1i3h9i3g8b0h5h5h5h5h5h8d8f5e1i3g7g7e0c0e3f5c1c8d7b5b8f0f0b2", -"a2a8a7a7a5d4c1e6c8c2c7c2d6d3f2e6b7a5h5h5i2j0f8j3g4f4h4h5h5i9g0g1j2b4g1i6d5e1b7a5h5h8i2i5b4j2g4f3h4h5h5e1g0g4b4b8i5h2h5h5h5i9b8f7j3j3g1i9i8d4e3c6h1a5h5b0i2f7b8e1h1h5h5h6a4g4b4b5g4a2d8c4d0e5e3e6d2h1b7h5h5c9i2i5g0h1h5h5h8a4i7b5j4f0j0g5g3c2c6b1h3h5h5g2a4i6h1h5h5c9b2j0f8j4f8i9i8d1d5f5f5e5e5c4c0f3h1h5h5c9a0b0h5h5g8j3a0g0g0j0i9i3d8f6c1e3d7c3c1d6e6e0d8c9h2h1a5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5h5g2j3b5i5i6e0c5c2c2g2g7h9a0a0e1g8h5h5h5h8i3f5e6d5d4e1g3d7f1g5f7a4b8g2h8h5h5h5c9d8e1h2h5h5h5i9i5g4j2j4b8i9i8c3g2c8h1a5h5b0i2f0h2b7h5h5i2g1f7a0b5j0g5i3e1d6c7d0c4c4c3d7h1h5h5c9a0i5j0b3h5h5h5b0i9i2b2j3a0j3a2b1h5h5c9a4f0b5b6i5h2h3h5h5g0i5f7j3f0i1h2h5h5h5i9b2b2i4i4i4b2b2b2a4a4a4a4a4a4a0g0b4g1i9f1i8i3i9g0b2i5c9b0i0h5h5g5d8g2e1g3f5d1c6d7c3c6d6e6b5j2f0b6b2", -"a2b0a7a7a5d5c7d7c4d0c1d0g6d2f4f3h1h5h5h8i2h9b5g0g1b1b7h5h5a4g1b6b4f8j0g7d1e5h1h5h5h6a4i5b5g0g4h2h3h5h5i9b8f7b4g0i7g9b7h5h5i9b8g0j3g0h9i6e1c1e5b1h4h5h5h6i4i5g0f4h3h5h5c9a0g1j2g0i5i6d8c4c6c1c1f3b7h3h5h5b0a4e8g4j3h1h5h5h8a4h9j2b4g4i1i3d0d6d3h1b7h5h5g0g0g3h4h5h5c9j4g4b4j4g1i6f1d5f9h2h2d7c9c9c2g9h3h5h5i3g0g7i0h5h5g2j3g0i5g5i8e1c1c5e5c2d0d8e5c7c6e0f5d7h0h3h5h5c9i9i9i9i9i9i9i9i9i9i9i9i9g2h5h5h6a4b4g1i6d8d5d0e5c3c3i8i9f7g0g0g8h5h5i0a0e1d8d0e3c3c4f2d8i8g5i5b8e8e8h8h5h5h8f0g7h2b7h5h5i9g4b6j3f8i5i6f5g2c1b1h4h5h5h6i4g4b1b7h5h5i2i5f8a0b8j1g7g7e5h2h2f9d7c5e5g9h4h5h5e1j2g4e6h1h5h5h8b2b2i9i1i5f0j2h2h3h5h5e5a4g0j2f0j0a6b7h5h5i2i7f8g0f0i9h2b7h5h5i9g1b8a0a0j2b8b8g1h9f4f9f4g1e9b8j2j2g1i9f1g2e1g7i9i5b8j3i9b0h5h5c9i9i8d8c1c6c0c2d0d8d1c7c6b5b5f8f8b2", -"a2b0a7a7a5d4e4c1c1c6c1f6f3e2f4f9h4h5h5h6a4g1b5b5g4a6b7h5b0i2h9f8b4b8i1f1c3f4h1h5h5g2j3i5b4b8i7b1b7h5h5i2g1f7b4b8i1f4b7h5h5g2b8g0j3b8i1f1g2e5f4h1a5h5h5i9j3g4b4h2h5h5h5i9j3f7j3g0h9e1g3e5e6c2f4a5h4h5h5h5i3i4j1e8j4b0h5h5b0a4j0b4j2i7g5i8d7c1b0h4h5h5h8i4j0j0h3h5h5h6a0b8j3b5h9i6d8e6b7h3b7h8d6b9d7b1h5h5h5g0b8b8f9h5h5b0i9i5i9g7d5d5e3d7c1e5c0e0e5c9c8c1d1h2h1h5h5b0a4b8f7j3a0a4a4b4g0b8f7g1g1h2h5h5b0i4j4g7a6a7g9e6e5d5c9d5f1j1g1g4h0i0h5h5i2i9f9b0h0f3e6d1d4d8f1i9h9g4a3h4h5h5h8b2i9f4b7h5h5g2f7e8j3b8i1f1d5g3f9h1b7h5h5i9g0g1g9a5h5h5g0g1j2a0e9g5e1g3h2h1b7h7h6d7e3h2h3h5h5i9b8j0f4h3h5h5e1a4g5i9f7f8b4j1h1b7h5h5i9b2b5b4g1i7b7a5h5h8i2j0e8j2g4a2g9h5h5h5i5b8e8a0j3b4j2b4b5e1h1h3h7c9b5g0g9b1b1a3f1e0d4c3g7j1j0b8d9h5i0h5c9j4g5i3d5c6c1e5c0d8d1c9c8g0f8e8f8b2", -"a2a7a7a9a5c3b9c2e6c2c0c4d2e4f3h2h3h5h5g2a0g4b4f8h9h1h5h5h8i4j0e8j2f7i9f5e6h2h3h5h5i9b8f7b4f0j1a5a5h5h8i2i7e8j4e9i9i8h5h5i0h8j3b5j3g1a2e0d4e3a5h3h5h5h8i4f7f0b4b1a5h5h5a4g1b6j4e8i7i8d5d0d7h2h1h3h5h5h5h6i2g1j0g0a0f4h5h5h5h9g4j3e8i9i3d8d1h2h1a5h5h5i9a4h9g0h2h5h5b0a4f0j3e8i9i6d8b1h1h5h5h8a2c9c5b0b7h5h5i2i5g0j4h8h5h5h8i5g5f1d8e5e6c8e6e5c1d8e5c9c7d5d9b7b7h5h5e1b2i9g1g0a0a0j3j3b5g0g0e8b4h2h5h5h5a4a0e1h4a5b0h6c0c4f2c2e5i6a2f4h1h5h5b0i2g4g9h3a5b0g8c4c0e6c3i8i6a3h2h4h5h5g8b2j0i9h5h5i0h8b4b5j3g1g5e1d8c7a5h3h5h5h8i4g1f0a2b7h5h5e1b8b4j3g4i6f5f2b7b7h5h5g2i8e6a7b7h5h5i2g1f0f4b7h5h5a4i5i7e8j2j4a0h2h4h5h5h5a4a0b5g0g4a2h1h5h5c9a4h9g0g0j0i6e6b7h5h5g2f7g0j4b4b6f7f7a2h0h3h5h5c9a0f0b1b7a5h8g7d4e3c0f1g7a2i1h0b7h5h5e1a4i5a2i8d1e5e5c1d8e5c9c7b5g0e8e8b2", -"a2a7a7a7a5d7c2c2c9c7c1f5b9d2e2b1b7h5h5i9g0b8j3b8g7h1h5h5c9a0i5e8e8g4g5c3d9a6b7h5h5a4i5g1j3e9i1h1h5h5h8b2j0b5j3g4g5e1b1i0h5b0g0g0b5j0i6d8d2h0h1h5h5b0g0a4h9b8j4h1a5h5b0i4i5f8j4f0i9d8f9a6b7h1b7h5h5h5g8i4j3i7b8b4b4a2b7h5h5c9g0b4f0i9e0g3h2h1b7h5h5c9i4j0g1j4f4a5i0h5i9b8g0i5i1i8h2h1a5h5h5e1g0g2f5b7a5h5h8i2j0f8j2j0h7h5h5h8j0g7g2c2e3e3c6c1e5e1c6c9d6d8b1h4h5h5h8i2h9j0e8j3j3j3b5g0b5b6e8g0b5f4b7i0h5i3a0h9h3h5h5g8g5d8d7g6c8g3f4b7h3h5h5c9i2f8e6b7h5h5i3i3d1d9c9d8e1h2h1b7h5h5i9a4b8j0h2h5h5b0g0g0j3i5i6e1f3h0h1h5h5b0g0a4h9b8j4h5h5h5h8a0j3j3j0i8d9a5h4h5h5b0i2i3c4h0a5h5b0i2i7b6f4h3h5h5a4j1g4b4j4j2h2b7b7h5h5b0i4b5b5g0g4e6h1h5h5c9g0g4b5g0h9g7f5h0h5h5h8b8e8j3e8i7a3c2b7h4h5h5b0i2b4h9h2a5h5h5j3d4c1f6f5c3e5b1h1h5h5b0a4a0b8i7g5d8f6c1e5e1c1c9d6j2g0b8b8b2", -"a2a7a7a7a5e3c2e5c8e5g3f5d2c9e4b0b7h5h5a4f0e8j4f0d9h4h5h5g2j3g1f8b6j0g5e5b9h0a5h5i0i2i7b6b4g1e6h1h5h5c9a0i5b5b5j0g7e1f2a5h5h5h8c2e1g3f3b1h1h4h5h5h5g2i4h9g1g0a2h1h5h5h8b2a6b1b1h1h1h1h1h3a5h5h5h5h5c9i4g0h9g1j2j4g0j0h2h5h5h5f3f1d8c2g9a5h1b7h5h5b0a0f7i9f8a0f0h5h5h5h8d9e1e5f4a5h1b7h5h5h8i2i7i3e1h1h5h5h6a4j0b5f8f7i3b0h5h5c9i9f1g2c6e3c3c6c1e1c2d6b9f4h1a5h5h5i9a0i9f7b5j4b5g1i5i5j0i7j0j0j0i8b7h5h5c9a4g0h0h5h5i0c7f3f9f9h2b0h1h3h5h5b0a4a0g0a1h3h5h5h8f3f4f4g9g9a5h1b7h5h5h8i2j3g0f0g7a5h5h5h8c2e1e5f3b1h1h4h5h5h5g2i4h9g1j2j4f4h5h5h5d7c2f1c2b1h1h4h5h5h5i3b2g7i8h1h5h5h6b2j0j2e1b7h5h5c9g3e1i8f4h0b7a5h5h5h5h8i2g0g0g0j0e6h3h5h5c9j1g3i1b8j1f1c3h2h5h5h5h6f4e5g3e4b1h1h3h5h5h5i9b2i9j1e4b7h5h5h6f9f4f9f4b1b7h1a5h5h5c9i4g0b5f0i1g7e1e5c1e1c2c9e7b5f8f8f0b2", -"a2a7a7a6a5f2c2c4c4c6c3d1d2d9d3h1a5h5b0i4g4g0b4f0g9h3h5h5i9b8g4g0e9h9i6e6g6h1a5h5h8i2i7b6g0g4f4h3h5h5i3g0g1j3f8h9g7f5e5g9i0h5h5b0h5h3h4h3a5h5h5h5c9i4i5i5g0j4e5h4h5h5b0h8a5a5a5a5h5h5h5h5h5h5h5h8i5i2f0i7f7e8j4b4f0i1i3h7h5h5h5h7h4h4h3h5h5h5h5b0b8b2a2i5b4b4f0d4b0h5h5b0b7b3h3b7h5h5h5b0a4a0i9i1e6h1h5h5g2j3g1b5g0j0i9e2i0h5h5e1g5f1d1e3f5c1c1f1b9b9d7b0h3h5h5h6i2h9i5f8b4j2g1i1g5i6i6i3i6i6i6g7h4h5h5h8a4b6i8h5h5h5b0a5b3h3h3h3a5h5h5b0i5i4i5b5b4f4h5h5h5b0h5h3h4h3h5h5h5h5h8a4a4f7f8g0j0d3i0h5h5b0h5h3h3h3a5h5h5h5c9i4i5h9g0j3b4g1h7h5h5h5h7h3h3h3a5h5h5h5g2i2i7i1e5h1h5h5c9a0i5b4j2h2h5h5h5h7h3b7h3h3i0i0b0h5h5g8a4b8b5f8i7i8h3h5h5b0g9h3f9i9i9e1c2d7h2h5h5h5b0h5h3h3h3a5h5h5b0e1i2i1i1j0i7h7h5h5h5h7b7h3h3h3b7h5h5h5h6i2b5f7j3g0h9i3i8c0c1f1b9b9d7b5f8f8b8b2", -"a2a7a6a9b3e4c1c6c6c1c1c1d2c9f3h2h5h5h8i4j0g0g0g4f3h7h5h5i2g4g1j2g1i7g7c8d2b1h5h5c9a4h9f8g0g4d9h7h5h5g0f7b6j3f7i7g7e0c4c2b9i0h5h5h5h5h5h5h5h5i0i3i4f7i1e9b4j4e1h2h5h5h5h5h5h5h5h5h5h5h5h5b0h6i5i2a0i7i5g1j2g0b4b8i7i6e1c3h8h5h5h5h5h5h5h5h5i0h8a4b2j1i7b8b4g0i5g5d7i0h5h5h5h5h5h5h5i0b0i5b2i9j0f0g3g9h5h5i9g0g4j3e8j0i6f1h6h5h5b0i9i6e0f6d8d4d1c6c8c9d2h2b0h5h5g0b5j1f0j2b4f0j1i3f1e1d8d4d8e1g3g3g9h5h5h5b2b6f0e1i0h5i0i0h5h5h5h5h5h5h8i5i4i1g4f8j4f7g8h5h5i0h5h5h5h5h5h5h5h6a4a4i7f7g0b5g4i9c2i0h5h5h5h5h5h5h5h5i0i3i4b8i7f7j3j4g0i7i6h8h5h5h5h5h5h5h5h5h5c9i2i5j1f7a2g9h5h5i3e8f0b4g0h9h8h5h5h5h5h5h5h5i0h8j3h5h5c9a4j2j2f0i7i6f9i0h5h5h5h5h5e5j1f1c5e7c7h6h5h5h5h5h5h5h5h5h5b0i5i4i7i9g4b6j0a3h8h5h5h5h5h5h5h5h5h5b0c9i2b5h9f8j4b5j0g5g7d5d1c6c8c9c2e8e8e8b6b2", -"a2a7a6a7b3f3c9d4d1e6g2f6c9e2c9c8h8c9i9a4i5j2g0j0i6h6g8c9i2j1b6j2g4i1i8d7d2d3h8c9i9g0i5b4f8h9i3g8h6c9i2g4f8j4e9i1f1f5d5c4c3i3c9i0h5h5h5h5h8e5b2i4i7i9b8b4j4g0i5c2h6c9c9c9c9c9c9c9c9c9i3j3i2i4j3i9i1g4g0b4g0g0f0i5i9f1e1f5e6e1h8h5h5h5h5b0h6i9i2j4i9i7f0b4j2f0i1g7g3i3g8i0i0h5h5h5h8e1i2i4i7j0b8b4f8g2g8c9a4f7b8j3f0i7i3e0e1c1c9c9i3i5i3e1g3d1e3c5c5c9g2d7h8g8i3i2j1g4j2j4f8j0g5e1d5c4d7e6e6c4e5g6c2h6c9c9a4b6f0h9i9c9i0h5h5h5h5b0g8i5i4a0i9i7e9j2j2g4i9g5h6h5h5h5h5h5h8c9g0i2g0i7i5g0j2b5i5g5e1i3c9i0h5h5h5h5h8e5b2i4i5i1g1b5j4j3g4i9f1e1e1h8h5h5h5h5b0g8b8i4g1i9g1j2j3i9g8c9g0f7f0j4f0j1g7e1h8h5h5h5h5h6i9i2j1h6c9i9a4j4j3e9i1g7g3h6h8h5h5h5h5i5f7f1d5e6d6e6g2h8i0h5h5h5b0h8i3i2b2j1i9g1b5j2e9i1i3i3h8h5h5h5h5h5h8e1a4i4f7j1g1j3j4g0h9i6e1c3e3c5c5c9e0b5g0f0f0b2", -"a2a6a6a7b7f2c1d5d5d1g3c9d3c5d9e5d5i1j0h9g4j2g0i7g7d5i3i7g4i7e8f8j0i9f1d9e4e7e0j0g1i5g4j2e8j1g7c3i8i5b6h9b5j3g1i9i8d8c1c3e6e1i3j3i2i9g0i2i4a4g4i9h9b8b5j3j3g4i1g7g5h9f7j3a4b2a4a4j4b5g0g1h9h9h9i7g1j2a0j4b6g4j0i9i3f5g2c9d7e0h9b2g0i9i2i2i4j3i7i1h9b8b5b4e8j0i6d8d0e1i3g0i2i9i2i2i2a4i5i9i5e8b4b4b6i5i9i5b8h9b8j3b6j1i8e1e5e1h9j3a0g0i9i3d8c3c5c7c0d4d5c4e1i9h9i1j1f0j4b4g1i1f1d8e5d7e4c8e3c1d6f4c9f6j1f7g0f0g0g4i9g5j3i2i5g0i2i2a4g0i9i9i7f7b5b4b6j0i6i8i3a0i2i9a4i2i4a4i5i9i7g1g0j3b4f7i7g7f5d5g7j3i2i9g0i2i4a4f7i7h9b8g0j4j3b8i7i6e0d8e1i5b2g0g0i2i2b2j3i9i7g1b5b4j2g4i9f7f7i5f0b4g4i9i8e1i9a4i5a4i2i2g0i9i9i5a0a4a4b4j2f0i9g7d5d9i6a0i5a4i2i2i5i6e1d4d7c2d5i9a4g0i5i2i2i2a0i5j1j0g1g0j3b5g1g5i8g7i7b2a4i9i2i2i2a4i5i7j1g1b5j3j3b8i1i3f5d4c5c7c0d4d5e8b8f0b6b2", -"a2a6a6a7b3d2d0e0c1e5f6d2d7d9c4d1c4c8f1g5g4g0f0i7i8c4e6c3i3i7f0f0i5a2e1d9e4d9d4e0i8i1i5g0f7j1i8d4c2e1i3i7b8b5i5g5i8d4f6d0c2c3f1g5i7b8b4e9j0h9j0i5b5j3j4j4b8i7i6e1c4f5g7j1b6j4j4j2e8e9g1b8e8e8e8b6j4a0j3e8j0a2g5i6g2c3d5d2c2d0g7i1g4b8b5j0h9h9j0f0e8j2b4e8g4i9f1e6d4g3f1f1i9i5j4b6g4g4i5e9f8j3j4g0i5i9g7e1i3j1f7g0g1i9i8d4e6c3f1g5i5g1h9g5e1c0d7e7d5d5d4d8c5e5e1i6h9e8b4e8h9i6e1e5e6d6c7e5e5c5d6d2e6d8e1i8a2j0g0f7i9i3g5g5i5g0g0g1i5i7i5g4b8b5j2b5i5a2i8d5e1g5j1g1j3b8g4j1i7j0b6b4j4j4b8j0g5i8g3e5e0g5i7f7j3b8j0i5i5f7g0b5j3j3b6h9g5g7c1c5d1e1g5h9b4b4f7g1i5g1e8j2j3b4f0h9i6g7i3i9f7g0g4i9i8g3d8i8i5j4j2g1i7j1g4g0g0j3j3g0j2g4i9g7g3b9d4e1a2b8b5b5g1j1i6f1d5c4c0g3a2i5g0e8i5h9i5g1f7g0b5b4b5e9i7i3f5e1i8i9i5g0j3g1i5i5i5g1b8b5j3j3e8j0i6f5e5d7c8e7d5d5d4j2b8b8e8b2", -"a1a6a6a8b7e5c4f6c1e6c2d6c9e7d1c0d7c5d8i3i1g1g4a2e1d4e6d8g7i9i5j0h9i6d4f2d7c7d4d5f1g5j1e9i5a2i8d4d4g2g7i1i5g1i7i3f1d5e5d0c2c4d5i8g5j1g4f7e8e8f8b4b4b5e8b8j1i6e1c3c1e6f1a2i5e8b5f8f8b6g0b5j2g0b6f0b5e8g4j1i6i6i8e1d4c1c2d6c7d6e1i3a2h9f7b6b6e8j2b5j2b5f0i5i9g7d8d6c3d4e6d4g7i9f7e8b5j2g0j3j3b4f8i5i1i3e1e1g7g5j0e9i5g5e1c4c2c4d8i8i9i7j0i9g7f6e3e5c2c8d7c4c5d7d8i3i1g4f0i5i9i8d5c5d7d3c2e6e6c9d2d2d5d8d5g3e1i7f7g4i9g7f1g7i1i5f8b5b8e8b5b5j2g0b6j0i9g7d8d5f5e1g5i1f0f8e8b6g0g0j3j3b4e8h9i9g7g2c0e5g2i8g5j0g1b8g0g0j3j3j3j3g0f7h9a2g7c3c2c8c2c0e1i9j0e9b6g0g0g0j3b4b5g1i7g5i8d8f1g5i7g4h9i6e1c1c8d5i1g4b6b6f0b5j3j3g0g0e9g1f7i7i9f1c1c9d0c3g7i1g1b8f8f0h9g5f1d1e5c2i3a2i7g4f0e8j2b4j3j3b5f8g1j1i6e1g2c3e0i3i9j0b6f8j2g0b4b5j2j3g0b6i5g5e1c1c2c9b9e6c2c8d7g0b8f0e8b2", -"a1a6a9a8b7e5c3e6e6c6c5d9c9e5e5d1d6c5c0d8i6i9i9i6e0d4c2d5f5i6i9i9i9g7d0d9f2d7d4f5e0g7i6i1i9g7f5d1d4d4e1i3i9i7i9i8g2d4c3c6c2g2e1f5e0g7i1j0g1f0e8e8f0g4i7a2i6e1f5e6d6d0g3i3i9h9j0h9j0h9i5j0i5j0i7h9j0h9g5g7c3d8e0e5e6c6c5d9c9c4d4e0f1g5i7j0g1b8b6b6f0i5i7a3i8e1d4c9e5d1c8e3d4g7i7g4b6e8b6b8f0g4i7i9i3e1e0f6e1i3i9i9i9i3e1e6c2g2e1d8e0i6i9i9i3f5e5c2d7d6b9b9c0e6g3e1i6i9j1i9i3d8e6g6d7f2e3c8e3c9g6d7g3f5e3e5e5g5i7i1g5e1g3d5g7i1i5f7f0b6b6f0g4j0j1a2g7e0c4c3c2f5f1g7i7g4g1f7f0f0f8b6g4i7i6i8f5c1e3e6f6f5g7i6j1g4e9b8f8f8g0g1j0i7i9i8c0d7c6d7d7e3g2i8g5j1i5g1f8b6e8g1h9i1i6i8d8d5d5d8g5a2a2i8d5c8d9d4i6i1j1i5g4e8g0f0i5h9i1i9i1i1i6e1c5c8e3c5g3i6i9g4f0f0j0i9f1e0c0c7d8g7i6i9j0f0f8b5f8b6i5h9i9g7f5f6c3c4f5d8g7i9i7g1b6g0g0b8f7b6g1j1i3e0c3c6d7c9c5d7d7c8b9f0b8b8e8b2", -"a1a6a8a8b3c4d4c1e6c7e6e7e7c0e5d9e4c7d7c0f5i8g7f1f5d1c3e5c0e1g7i8g7f1d0c9d9d9f6d5f5e0f1g7i8e0d4d1c2e5f6e1g7i6g7e0c3c3c6d0c5e1e0d4e1d8i8i6i9j1i1j1i1g5i6f1d8g3d0c7d7c5d1d8g7i6i6g7i6g5g5i3i6g7g5a2g5g7d8g3d4c3c3e6e6c7e6e7e7c0e5c2e6d8g7g5i9i1i7j1i1a2i6i8d5c4e5c9d1f6d7d6e6d4i6a2j1h9i7j1i9g5i3g7f5f6c1g3d5e1i8i6g7i8f6d0c5e1e0d4f1e1g7g7f1d8e6d7d7c8c7c9d7c1c1c0e1g7i3g7e1c3e3f2d9c2e6f2e4e2e5d5f5e5c8c2d5f1i6i3i8c3d1c2d4i3g5a2i9i1i1i1a2i6i3f1f5c3d5e6c2c4g3f5i6i9i9i1i1i1i7j1a2i6e1c3c2c7d7c1c2c4c3e1g7i9i9i7i7j0j1i9i6g5g7d5d8c2c5d7c8c2e6e5e1g7g5i9j1i7j1a2i6i8e1f5c4c4e6e6d8g7g7c3c5f2c4d8f1f1i3a2i1h9h9i1g5g7g7f1i8i6f1e6c9c9d9c5c6g3i3a2i1i7j1g5e1c3e5d6c3e1e0i8i6i9h9j0h9i7g5i3e1d5c1d1c2c1d0f5d8g7i3i9i1h9h9i7i1i7i9g7g7d4d0d7c8c2d7d7d7d6c7f7b6e8b6b2", -"a1b0a8a9b3f6d7c2c6d7d7e7c4d4e5e7d9e2e4d7c6e6g3d1c2c4c1d4c6c0d8e1d8d8c9b9c6d6f6c4d5d8d1d4d4c0d4c6c2c2c2f5g2e1d5g2c1c1c6c1c3c4e6d1e5g2d5f5e1i8i6g7i8g3d8c1c1c1c7c5d7e6c4c3d5e1d1g3e1e1e1g3d4d4e1e1f1c5c2c6c1f6d7c2c6d7d7e7c4d4e5d6c7c8e5d8e1e1i8i8e0f1e0f5c1c2c0d1d0d5e7b9c6c2e1f1i3i6i8i8e1e0e0c3c1e6c5c3c1g2g2e0d5d5c1c1c3c4d0d1e5g2d5c3f6c4g3c2c2e4c5c9e3e6c7c1c1d8d8d8e5e5f2c7c2d0d0d9d3b9e6g3f5e4c7e3c4d8f6d8f5c1c2c9d5e0e1e0e1e1e1e1e0c3d4e5c2c0c1d4c2c2d4f5d8g7d8e1g7f1i3g7i8f1e5c6c7d7c1c6c2c5c6f5g2f1i8i3g7i3i8f1e1d8d4c3c2d1c5c7c8d7c3c1d4e5f1e1i8g7f1f1d8d8c3c4e6d0e4c5c3d8d8e6d9b9e6d5d8c2c3e1g7i6i8i8e1g3f6c0e1e1g2d7d9e2e4c9d7c2d5d8e1i3g7i8c3c0d4d1e5f5c5c0e1e1i6i3i6i3e1f5c1c2e5c6c2c2c5c3e5d8f5i8i8i3g7g7i3i8e1d8d4c3c2c8c8d7d1c2c2b9c5f7b6e8f0b2", -"a1b0a8a7b3d5c5c6e3d7d9e5d4d1e7d6f2f3d2e4d7c5d0c4e5d1e5c2d7e5e5e5d4c2e3e7c8e3d4d1d5f5e3c6c2c1c2e5e3e6e5e5c3e5g2e5e3c6e6c2g2c2c2c5c5c0c6e5e0d5e1d5c0c4e6c1e3c6c7b9c7c7c8d0e6c2c7d4c4c4e6c8d9d2d5e1d8b9c7e5c1d5c5c6e3d7d9e5d4d1b9d6g6g6e4d7e6d1c3g3c3g2d4c6d7e5c6d0c0e3c8e7c8e3c3g3e0e1d4d1c0c0c1c4e3e6e5c1d4c2g2c4c2c1d0c2g2c2c2c5c5c0c6e6e0c1d5c2c8d7c5e6d7c6d7b9e3c5c2c1c6d7e7e6d0e6c7b9g6d2d4d8d8b9c9e5c1d5d0e5c6e3d6e5c3c3d7e6c5d7d9c6c2e6e6c0d0d1e5c2d7e5c6d0d4c1c0c1c4c3e0d8d8d8d7e3d7c5c5e5e3e6e5e5c3e5e0g2d4c3c3d4e0c2e6c5c5e5c5c2f5e6d5c6d7e6c1c3d4d5e5d7c2c5c8e6c5d7e7d0c1c4c2b9e4d2c3d8d8b9d7d5g3e1d4d4c1c6d6d1d5c3d6d6f2f3d2b9d9d7d0d5d5e0g2d1c6d1c6d0e5e3c8d7d0c0e0e0e1e1e6c6e3c2c2e5e3e6e5c1d1c2e0d1c4c3d5c3e1c1c1c6c5e5c5c2f5e6d5c6c8d7c5e8b6e8f0b2", -"a1a8a7a9b3b9e3c5c8c8e2e5d1d3g6e4d2g6d2g6d3d2d9d6c6c0d7d1c5d0f5c0e3e7d7e7d6d6e5c3d5d5d7c8c7e3c1c1d7c6c6c2d4c3c6c4c3e5c6c1c2c7e3d0c4d7c3g2c3e5d5c1c8d3c5c5c8d9d6c8e3c5d7e5e6e6c2d0c1e3b9d7c9d2d5d8d4c9d1d0e6b9e3c5c8c8e2e5d1d3g6e4d2g6d2g6d3g6d6c7c1e5d7d1c5c1f5c0e3e7d7e7d6d6e5c3d5f5c5d7c7e3c1c1d7c6c6c2d4c3c6c4c3e5c6c1c2d7e3d0c4d7c3g2d4e6d5d0c7d3c5c5c8d9e7d7e3c5d7e5e6e6c5d0c1c5b9d7c9d2d5f5d4d6d1d0e6d9e3c5c8c8e2d0d1d3g6e4d2f2f3g6d3d2d9d6c6c0d7d1c5c1f5c0e3e7d7e7c7d6e5c3d5f5d7c8c7e3c1c1d7c6c6c2d4c3c2d1d5e5c6c1c2d7e3d0c4d7c3g2d4d0d5d0c7d3c5c5d7d6e7d7e3c5d7e5e6e6c5e6c1c5e4d7e7d2d5f5d4c9d1d0c1b9e3c5c8c8d2c0d1b9g6e4d2g6d2g6d3d2d9d6d0c0c5d1c5d0f5e5e3e7d7e7d6c7c4g3d5d5d7c8c7e3c1c1d7c6c6c2d4c3c5c4c3e5c6c1c2c7e3d0c4c5d4g2d4d0d5d0c7d3c5b6b6f0f7b2", -"a2a8a6a7b3d9c2c2c8c8c1e5c4g6d9e2d2d2d2e4d3d2b9c1e5c5c3c5d1c7f5d0g6c9b9d6c2e7e5f5c3c0e7d6c9e6d7c1d7e3c6d4d0e5c1c6c1e3e6c1c8c5c8c1d7d4e5f6c2c1e6d7b9c5e3d7e4c9c7d7d7c2d0e6c6d0e5d0e6b9e4d6c2e4d8d5c7c9c3c4e5d9c2c2c8c8c1e5c4g6d9e2d2d2d2e4e4d2b9c1e5c5c3c5d1c7f5d0g6c9b9d6c2e7c4d8f6c0e7d6c9e6d7c1d7e3c6d4d0e5c1c6c1e3e6e5c8c5c8c1d7d4e5f6c6c1e6d7b9c5e3d7e4c9c7d7d7c2d0e6e6d0d0d0e6b9e4d6d7e4g3d5c7c9c3c4e5d9c2c2c8c8c1e5c4g6d9e2g6d2d2e4e4d2b9c1e5c5c3c5d1c7f5d0g6c9b9d6c2e7e5f5f6c0e7d6c9e6d7c1d7e3c6d4d0e5c1c6c1e3e6c1c8c5c8c1d7d4e5f6c6c1e6d7b9c5e3d7e4c9c7d7d7c2d0e6e6d0d0d0e6e7f2c9c2e4d5d8c7c9c3c4e5d9c2c2c8c8e5c1c4g6d9e2d2d2d2d3d3d2b9c1e5c5c3c5d1c7f5d0g6c9b9d6c2e7c1f5f6c0e7d6c9e6d7c1d7e3c6d4d0e5c1c6c1e3e6e5c8c5c8c1d7d1e5f6c6c1e6d7b9c5e3b6f0f0b6b2", -"a2a8a7a6b3c8e6d9e3c7f6c0c9d3c9g6f3d2f3e4d2d2b9e6c6c9e2c5c5b9d0e5d2g6d3b9d6c9c6d8d4c9c9d6d6c2e3d0e3c2c0c2f6c6d4c2c8c1e6c6e3c1c5c3d4d1d4c5e6e5c7d7e3c2c2b9d3b9d6c8c2d6c1c5d0d0d0e6e3f2c9c8c8d2d5d8c8c9c4f6c7c8e6d9e3c7f6c0c9d3c9g6f3d2d2b9d2d2b9e6c6c9e2c5c5b9d0e5d2g6d3b9d6c9c6d8d1c9c9d6d6c2e3d0e3c2c0c2f6c6d4c2c8c1e6c6e3c1c5c3d4d1d4c5e6e5c7d7e3c2c2b9d3b9d6c8c2d6c1c5d0d0c1e6e3f2c9d7c8d2d5d8c8c9c4f6c7c8e6d9e3c7f6c0c9d3d9g6f3d2d2b9d2d2b9e6c6c9e2c5c5b9d0e5d2g6d3b9d6c9c6d8d4c9c9d6d6c2e3d0e3c2c0c2d4c6d4c2c8c1e6c6e3c1c5c3d4d1d4c5e6e5c7d7e3c2c2b9d3b9d6c8c2d6c1c5d0d0c1e6e3f2c9d7c7d2d5d8c8c9c4f6c7c8e6d9e3c7f6c0c9d3d9g6f3d2f3b9d2d2b9e6c6c9e2c5c5b9d0e5d2g6d3b9d6c9c6d8d4c9c9d6d6c2e3d0e3c2c0c2f6c6d4c2c8c1e6c6e3c1c5c3d4d1d4c5e6e5c7d7e3c2c2f0f0f0f0b2", -"a2b0b0a8b3d5d5c1e3d4e5d1d6d7d9d3d2e2d2g6g6e3d7e7d7c9e4c4e2b9c4c3f4b9c2c9e3d4c4d8c1c7d6c9c2d7c6c1c1e5c2d1c1c1e5c6c7e3e6c5c2d8e0e0f6c4e6c0d4c3c7c2c2c2c9d7d3b9c7c2c2d7e6d7d0e6e3d7d6d7c7c8e7d0e6d4c8d6b9d7c8d5d5c1e3d4e5d1d6d7d9d3d2e2d2g6g6e3d7e7d7c9e4c4e2b9c4c3f4b9c2c9e3d4c4d8c1c7d6c9c2d7c6c1c1e5c2d1c1c1e5c6c7e3e6c5c2d8e0e0f6c4e6c0d4c3c7c2c2c2c9d7d3b9c7c2c2d7e6d7d0e6e3d7d6d7c7c8e7d0e6d4c8d6b9d7c8d5d5c1e3d4e5d1d6d7b9d3d2f2d2g6g6e3d7e7d7c9e4c4e2b9c4c3f4b9c2c9e3d4c4d8c1c7d6c9c2d7c6c1c1e5c2d1e5c1e5c6c7e3e6c5c2d8e0e0f6c4e6c0d4c3c7c2c2c2c9d7d3b9c7c2c2d7e6d7d0e6e3d7d6d7c7c8e7d0e6d4c8d6b9d7c8d5d5c1e3d4e5d1d6d7b9d3d2e2d2g6g6e3d7e7d7c9e4c4e2b9c4c3f4b9c2c9e3d4c4d8c1c7d6c9c2d7c6c1c1e5c2d1c1c1e5c6c7e3e6c5c2d8e0e0f6c4e6c0d4c3c7c2c2c2c9b6f7f0f0b2", -"a2b0b0a8a5g2f5c8c2d4c4d9d7d7d2f2d2d2g6e4f2c5d7b9e6d3c5d7e4c4f5e5c9c6c2d7d5d1e5c1c4c9d7c6d7e6e6c6d4d4e5c6d0d4e3e3c6c6d7c2d0c3e0c2d0c1c4d5d5d1c2e6c2e7e3d9d3d2b9b9c9d3c8b9e3f2c9b9b9e2c7c7d2e3c1c9c8f3d3d7f5g2f5c8c2d4c4d9d7d7d2f2d2d2g6e4f2c5d7b9e6d3c5d7e4c4f5e5c9c6c2d7d5d1e5c1c4c9d7c6d7e6e6c6d4d4e5c6d0d4e3e3c6c6d7c2d0c3e0c2d0c1c4d5d5d1c2e6c2e7e3d9d3d2b9b9c9d3c8b9e3f2c9b9b9e2c7c7d2c5c1c9c8f3d3d7f5g2f5c8c2d4c4d9d7d7d2f2d2d2g6e4f2d7d7b9e6d3c5d7e4c4f5e5c9c6c2d7d5d1e5c1c4c9d7c6d7e6e6c6d4d4e5c2d0d4e3e3c6c6d7c2d0c3e0c2d0c1c4d5d5d1c2e6c2e7e3d9d3d2b9b9c9d3c8b9e3f2c9b9b9e2c7c7d2e3e6c9c8f3d3d7f5g2f5c8c2d4c4d9d7d7d2f2d2d2g6e4f2c5d7b9e6d3c5d7e4c4f5e5c9c6c2d7d5d1e5c1c4c9d7c6d7e6e6c6d4d4e5c6d0d4e3e3c6c6d7c2d0c3e0c2d0c1c4d5d5d1c2e6c2e7e3f0e9g1f7b2", -"a2b0b0a8a5c3c8c6c5e3c9c7d7f3d3d2g6g6d2e4b9b9d7d7b9d7c0b9c5c4e5c5b9b9d7d7c3c4c0c1c4d9c2c6c5e3c6e5d4d1c4c3c1d4c6c4d4d6c2d6c6d5f1d8e3e3e5d5d5c1c7c7c7c9e3c9d3b9f2b9d6b9d6b9d3e2b9g6c9f2b9d2d2e6c1c7c8e4b9c8d5c3c8c6c5e3c9c7d7f3d3d2g6g6d2e4b9b9d7d7b9d7c0b9c5c4e5c5b9b9d7d7c3c4c0c1c4d9c2c6c5e3c6e5d4d1c4c3c1d4c6c4d4d6c2d6c6d5f1d8e3e3e5d5d5c1c7c7c7c9e3c9d3b9f2b9d6b9d6b9d3e2b9g6c9f2b9d2d2e6c1c7c8e4b9c8d5c3c8c6c5e3c9c7d7f3d3d2g6g6d2f2b9b9d7d7b9d7c0b9c5c4e5c5b9b9d7d7c3c4c0c1c4d9c2c6c5e3c6e5d4d1c4c3c1d4c6c4d4d6c2d6c6d5f1d8e3e3e5d5d5c1c7c7c7c9e3c9d3b9f2b9d6b9d6b9d3e2b9g6c9f2b9d2d2e5c1c7c8e4b9c8d5c3c8c6c5e3c9c7d7f3d3d2g6g6d2e4b9b9d7d7b9d7c0b9c5c4e5c5b9b9d7d7c3c4c0c1c4d9c2c6c5e3c6e5d4d1c4c3c1d4c6c4d4d6c2d6c6d5f1d8e3e3e5d5d5c1c7c7c7c9d7f0e9f7g1b2", -"a2b0b0a8b3c6c6e5c5e3c7c8f2d2g6b9b9d2b9e4d6d7c5c9c0b9b9c0d0e5f5e3d7c3f5e0d8d5e5c0c0d9c7e3d7d6e5e6d4d1c6d4c5c0c3c2d7c7d7c2c1d8d8e5c6d7c2c0c3d7c9d6e3d7c9b9c9d6b9b9c8c8e4b9c7d3e2d6d3b9b9d2d2f4b9c5c7e2c9d7e5c6c6e5c5e3c7c8f2d2g6b9d3d2b9e4d6d7c5c9c0b9b9c0d0e5f5e3d7c3f5e0d8d5e5c0c0d9c7e3d7d6e5e6d4d1c6d4c5c0c3c2d7c7d7c2c1d8d8e5c6d7c2c0c3d7c9d6e3d7c9b9c9d6b9b9c8c8e4b9c7d3e2d6d3b9b9d2d2f4b9c5c7e2c9d7e5c6c6e5c5e3c7c8f2d2g6b9d3d2b9e4d6d7c5c9c0b9b9c0d0e5f5e3d7c3f5e0d8d5e5c0c0d9c7e3d7d6e5e6d4d1c6d4c5c0c3c2d7c7d7c2c1d8d8e5c6d7c2c0c3d7c9d6e3d7c9b9c9d6b9b9c8c8e4b9c7d3e2d6d3b9b9d2d2f4f2c5d7e2c9d7e5c6c6e5c5e3c7c8f2d2g6b9b9d2b9e4d6d7c5c9c0b9b9c0d0e5f5e3d7c3f5e0d8d5e5c0c0d9c7e3d7d6e5e6d4d1c6d4c5c0c3c2d7c7d7c2c1d8d8e5c6d7c2c0c3d7c9d6e3d7c9f7f0b6f0b2", -"a2b0a7a6b3d0e5e3e3e3c6c8d6c4d0e2b9g6d6d6d7e6b9c0d7c1b9b9d5c3d4c6g2d8d8d8e0c7e5e5f2c9d7d7d7e7c2d1d1d4d0d1d0e5c6c6e6c1d7d7c3e1c2c4e6c2e5f6d4c8c7c8c6c5e3d9c9c9e4d7c8b9f2c9d9d3c9c8e4b9b9e3c5g6e4e6c2e2d4d4c6d0e5e3e3e3c6c8d6c4d0e2f2f2d6d6d7e6b9c0d7c1b9b9d5c3d4c6g2d8d8d8e0c7e5e5f2c9d7d7d7e7c2d1d1d4d0d1d0e5c6c6e6c1d7d7c3e1c2c4e6c2e5f6d4c8c7c8c6c5e3d9c9c9e4d7c8b9f2c9d9d3c9c8e4b9b9e3c5g6e4e6c2e2d4d4c6d0e5e3e3e3c6c8d6c4d0e2f2f2d6d6d7e6b9c0d7c1b9b9d5c3d4c6g2d8d8d8e0c7e5e5f2c9d7d7d7e7c2d1d1d4d0d1d0e5c6c6e6c1d7d7c3e1c2c4e6c2e5f6d4c8c7c8c6c5e3d9c9c9e4d7c8b9f2c9d9d3c9c8e4b9b9c5c8g6e4e6c2e2d4d4c6d0e5e3e3e3c6c8d6c4d0e2b9g6d6d6d7e6b9c0d7c1b9b9d5c3d4c6g2d8d8d8e0c7e5e5f2c9d7d7d7e7c2d1d1d4d0d1d0e5c6c6e6c1d7d7c3e1c2c4e6c2e5f6d4c8c7c8c6c5e3f0e9f0f0b2", -"a2a8a7a6b3c2c6c9c8e3d7d7g6e6e6g6f3f2d7c7e3c2c5c2c5d7c1e5f5g3g3c2f5d8e6c1e6c6d5c6d2d2c6c2e7d9e3c3c3e5c1f6c6c1c8c5d0e5c0d7c2f6b9c2e5e6d1d4c2c7e3e3c1c1c1c8d6e7d7c7d6b9d3d6d3c9c7c9b9b9c8e6c8c9c7e3c1b9c4c4c2c2c6c9c8e3d7d7g6e6e6g6g6f2d7c7e3c2c5c2c5d7c1e5f5g3g3c2f5d8e6c1e6c6d5c6d2d2c6c2e7d9e3c3c3e5c1f6c6c1c8c5d0e5c0d7c2f6b9c2e5e6d1d4c2c7e3e3c1c1c1c8d6e7d7c7d6b9d3d6d3c9c7c9b9b9c8e6c8c9c7e3c1b9c4c4c2c2c6c9c8e3d7d7g6e6e6g6g6f2d7c7e3c2c5c2c5d7c1e5f5g3g3c2f5d8e6c1e6c6d5c6d2d2c6c2e7d9e3c3c3e5c1f6c6c1c8c5d0e5c0d7c2f6b9c2e5e6d1d4c2c7e3e3c1c1c1c8d6e7d7c7d6b9d3d6d3c9c7c9b9b9d7e6c8c9c7e3c1b9c4c4c2c2c6c9c8e3d7d7g6e6e6g6f3f2d7c7e3c2c5c2c5d7c1e5f5g3g3c2f5d8e6c1e6c6d5c6d2d2c6c2e7d9e3c3c3e5c1f6c6c1c8c5d0e5c0d7c2f6b9c2e5e6d1d4c2c7e3e3c1c1c1b6f0f7b6b2", -"a2a8a6a6b3c8d9d6c8c7d2f3e6e6e6f3c8c5e6e3d7d7d9c7c2e5c2e6d8d8c5d7c6c6d0c2c1e6d5c3c8c1d7d7e3c1f6d1g3c1e5g2d4c6c5c2d4c1c1e3e6c5c3c2d5d5g2e6d7c9c2c6c1c1e5c9e4d6d6e4c7c7d7c8c9e7c9b9d6c2e6c2d3c9f2e6d3e3f5c3d6c8d9d6c8c7d2f3e6e6e6f3c7c5e6e3d7d7d9c7c2e5c2e6d8d8c5d7c6c6d0c2c1e6d5c3c8c1d7d7e3c1f6d1g3c1e5g2d4c6c5c2d4c1c1e3e6c5c3c2d5d5g2e6d7c9c2c6c1c1e5c9e4d6d6e4c7c7d7c8c9e7c9b9d6c2e6c2d3c9f2e6d3e3f5c3d6c8d9d6c8c7d2f3e6e6e6f3c7c5e6e3d7d7d9c7c2e5c2e6d8d8c5d7c6c6d0c2c1e6d5c3c8c1d7d7e3c1f6d1g3c1e5g2d4c6c5c2d4c1c1e3e6c5c3c2d5d5g2e6d7c9c2c6c1c1e5c9e4d6d6e4c7c7d7c8c9e7c9b9d6c2e6c2d3c9f2e6d3e3f5c3d6c8d9d6c8c7d2f3e6e6e6f3c8c5e6e3d7d7d9c7c2e5c2e6d8d8c5d7c6c6d0c2c1e6d5c3c8c1d7d7e3c1f6d1g3c1e5g2d4c6c5c2d4c1c1e3e6c5c3c2d5d5g2e6d7c9c2c6c1c1e5f0f0f0f0b2", -"a2a7a6a7b3c8e7e7c8c7d2g6e6e6g6d9e5c5d7c2d7c6d9c9c2c0d1d1c6c1d7c6f6c4c0c5c4d7d7c7c2c4c5e6c5e5c3c3c3c4d0g2c4c3d7c2e6e6c6c5c1c2d5c5c4d5c1c6c5e3c6c1c2c5c6c2d7d6d7c8e2d7c7c9d9d7d9e3c5c2e3c1e4f2g6c9d3e5d5c6d6c8e7e7c8c7d2g6e6e6g6d9e5c5d7c2d7c6d9c9c2c0d1d1c6c1d7c6f6c4c0c5c4d7d7c7c2c4c5e6c5e5c3c3c3c4d0g2c4c3d7c2e6e6c6c5c1c2d5c5c4d5c1c6c5e3c6c1c2c5c6c2d7d6d7c8e2d7c7c9d9d7d9e3c5c2e3c1e4f2g6c9d3e5d5c6d6c8e7e7c8c7d2g6e6e6g6d9e5c5d7c2d7c6d9c9c2c0d1d1c6c1d7c6f6c4c0c5c4d7d7c7c2c4c5e6c5e5c3c3c3c4d0g2c4c3d7c2e6e6c6c5c1c2d5c5c4d5c1c6c5e3c6c1c2c5c6c2d7d6d7c8e2d7c7c9d9d7d9e3c5c2e3c1e4f2g6c9d3e5d5c6d6c8e7e7c8c7d2g6e6e6g6d9e5c5d7c2d7c6d9c9c2c0d1d1c6c1d7c6f6c4c0c5c4d7d7c7c2c4c5e6c5e5c3c3c3c4d0g2c4c3d7c2e6e6c6c5c1c2d5c5c4d5c1c6c5e3c6c1c2c5c6b8b6f0b6b2", -"a2a7a9a8b3c7c9c7d7c7g6e5e6c1f2d9c4c4e6e3c5c5b9b9e5e5d9c1e5e5e3c3c6e5c1e5d0d1c8c5e5c6e5e6c1e5d4c0d5c3c0d8e5e5c2e3d6c6c5d6c2c7e4b9c2c2c1c2c6c2c1c1e3c5c6c4b9e5b9d7c7e3c5f2d7d9c7e6d0c5d2e4b9g6d2d3e5c4e3d7d6c7c9c7d7c7g6e5e6c1f2d9c4c4e6e3c5c5b9b9e5e5d9c1e5e5e3c3c6e5c1e5d0d1c8c5e5c6e5e6c1e5d4c0d5c3c0d8e5e5c2e3d6c6c5d6c2c7e4b9c2c2c1c2c6c2c1c1e3c5c6c4b9e5b9d7c7e3c5f2d7d9c7e6d0c5d2e4b9g6d2d3e5c4e3d7d6c7c9c7d7c7g6e5e6c1f2d9c4c4e6e3c5c5b9b9e5e5d9c1e5e5e3c3c6e5c1e5d0d1c8c5e5c6e5e6c1e5d4c0d5c3c0d8e5e5c2e3d6c6c5d6c2c7e4b9c2c2c1c2c6c2c1c1e3c5c6c4b9e5b9d7c7e3c5f2d7d9c7e6d0c5d2e4b9g6d2d3e5c4e3d7d6c7c9c7d7c7g6e5e6c1f2d9c4c4e6e3c5c5b9b9e5e5d9c1e5e5e3c3c6e5c1e5d0d1c8c5e5c6e5e6c1e5d4c0d5c3c0d8e5e5c2e3d6c6c5d6c2c7e4b9c2c2c1c2c6c2c1c1e3c5c6f8f0b8f0b2", -"a2a7a9a8b3d9c7c8d7c8c7d4e6g6e4c1c4c8e5d7d9c7c8c1b9c0e1d8g2c0d5e5c0c6e6c1c1e5d7c8c4c2e5g2d5d1d0e3c1c4d5c3c8d6c0c8d7c7c2d6c5e7b9b9d6d7c6c1c8e3e6e6c5c6e6e3e5d0c9c6c7c9c9d7d7c2c1d4d0c9d3b9d2e2f4d6c2e5d0c7c9d9c7c8d7c8c7d4e6g6e4c1c4c8e5d7d9c7c8c1b9c0e1d8g2c0d5e5c0c6e6c1c1e5d7c8c4c2e5g2d5d1d0e3c1c4d5c3c8d6c0c8d7c7c2d6c5e7b9b9d6d7c6c1c8e3e6e6c5c6e6e3e5d0c9c6c7c9c9d7d7c2c1d4d0c9d3b9d2e2f4d6c2e5d0c7c9d9c7c8d7c8c7d4e6g6e4c1c4c8e5d7d9c7c8c1b9c0e1d8g2c0d5e5c0c6e6c1c1e5d7c8c4c2e5g2d5d1d0e3c1c4d5c3c8d6c0c8d7c7c2d6c5e7b9b9d6d7c6c1c8e3e6e6c5c6e6e3e5d0c9c6c7c9c9d7d7c2c1d4d0c9d3b9d2e2f4d6c2e5d0c7c9d9c7c8d7c8c7d4e6g6e4c1c4c8e5d7d9c7c8c1b9c0e1d8g2c0d5e5c0c6e6c1c1e5d7c8c4c2e5g2d5d1d0e3c1c4d5c3c8d6c0c8d7c7c2d6c5e7b9b9d6d7c6c1c8e3e6e6c5c6e6b8b8b8f0b2", -"a1a7a9b0b3d6e7c5e3g6c1d4c7d2e2d6c5c2c5c7c8c5c0c1c5e5c4e0c4e3c0e6c1d0c8c4c1f6c2d4c5c1d5c6e6c6e3e3c5d5f5c1c1d6c1c6d7c8b9d9c7c9b9c2c2c5g2d4c5c3c4c5d7c1c1c8e5d1c6d6c5b9c5d6e3d1c1c2d7d3b9d6d2c9d3c4c2e5c6c7c9d6e7c5e3g6c1d4c7d2e2d6c5c2c5c7c8c5c0c1c5e5c4e0c4e3c0e6c1d0c8c4c1f6c2d4c5c1d5c6e6c6e3e3c5d5f5c1c1d6c1c6d7c8b9d9c7c9b9c2c2c5g2d4c5c3c4c5d7c1c1c8e5d1c6d6c5b9c5d6e3d1c1c2d7d3b9d6d2c9d3c4c2e5c6c7c9d6e7c5e3g6c1d4c7d2e2d6c5c2c5c7c8c5c0c1c5e5c4e0c4e3c0e6c1d0c8c4c1f6c2d4c5c1d5c6e6c6e3e3c5d5f5c1c1d6c1c6d7c8b9d9c7c9b9c2c2c5g2d4c5c3c4c5d7c1c1c8e5d1c6d6c5b9c5d6e3d1c1c2d7d3b9d6d2c9d3c4c2e5c6c7c9d6e7c5e3g6c1d4c7d2e2d6c5c2c5c7c8c5c0c1c5e5c4e0c4e3c0e6c1d0c8c4c1f6c2d4c5c1d5c6e6c6e3e3c5d5f5c1c1d6c1c6d7c8b9d9c7c9b9c2c2c5g2d4c5c3c4c5d7c1e5b6b8f8b8b2", -"a2b0a9a8b3c8e7e3c2c4c8c8d2d2g6c5e6e6c6c7d7c2c5c1e5c0d4e5e3c7g2c3e6e3c4c2e3c6c0f6f5e5c1c5c6d7e3e3c4f6g2e5c7c1c0c7d7c1d7d6c9c8g6c2d5c1e1g2d4c1b9c4c2d5d4c2d0c0e6c2c2b9c1d6c1d1c2g2c1b9b9c1e6d3c2d5d6d3d0c7c7c7e7e3c2c4c8c8d2d2g6c5e6e6c6c7d7c2c5c1e5c0d4e5e3c7g2c3e6e3c4c2e3c6c0f6f5e5c1c5c6d7e3e3c4f6g2e5c7c1c0c7d7c1d7d6c9c8g6c2d5c1e1g2d4c1b9c4c2d5d4c2d0c0e6c2c2b9c1d6c1d1c2g2c1b9b9c1e6d3c2d5d6d3d0c7c7c7e7e3c2c4c8c8d2d2g6c5e6e6c6c7d7c2c5c1e5c0d4e5e3c7g2c3e6e3c4c2e3c6c0f6f5e5c1c5c6d7e3e3c4f6g2e5c7c1c0c7d7c1d7d6c9c8g6c2d5c1e1g2d4c1b9c4c2d5d4c2d0c0e6c2c2b9c1d6c1d1c2g2c1b9b9c1e6d3c2d5d6d3d0c7c7c7e7e3c2c4c8c8d2d2g6c5e6e6c6c7d7c2c5c1e5c0d4e5e3c7g2c3e6e3c4c2e3c6c0f6f5e5c1c5c6d7e3e3c4f6g2e5c7c1c0c7d7c1d7d6c9c8g6c2d5c1e1g2d4c1b9c4c2d5d4b8b8e8b8b2", -"a2b0a9a9b3c7e3c5c8e6c5f9e4e7d7e5c8c8d7c7c2c2c1d4c5c6c2c6c0e5c4d4c4e3c2d7d7e3c0e5c5d7c6c2c5d0c5d5c4d4d1c5d6c8d5c1c2e6d5c6c7f2e4e1e1e0e0d5d4c4c1c4c1c1e5c4d7c9c5e6g3c6c6c0e6e6e7c2e6b9c1f5d5b9d5d5d9d3e6d7c7c7e3c5c8e6c5f9e4e7d7e5c8c8d7c7c2c2c1d4c5c6c2c6c0e5c4d4c4e3c2d7d7e3c0e5c5d7c6c2c5d0c5d5c4d4d1c5d6c8d5c1c2e6d5c6c7f2e4e1e1e0e0d5d4c4c1c4c1c1e5c4d7c9c5e6g3c6c6c0e6e6e7c2e6b9c1f5d5b9d5d5d9d3e6d7c7c7e3c5c8e6c5f9e4e7d7e5c8c8d7c7c2c2c1d4c5c6c2c6c0e5c4d4c4e3c2d7d7e3c0e5c5d7c6c2c5d0c5d5c4d4d1c5d6c8d5c1c2e6d5c6c7f2e4e1e1e0e0d5d4c4c1c4c1c1e5c4d7c9c5e6g3c6c6c0e6e6e7c2e6b9c1f5d5b9d5d5d9d3e6d7c7c7e3c5c8e6c5f9e4e7d7e5c8c8d7c7c2c2c1d4c5c6c2c6c0e5c4d4c4e3c2d7d7e3c0e5c5d7c6c2c5d0c5d5c4d4d1c5d6c8d5c1c2e6d5c6c7f2e4e1e1e0e0d5d4c4c1c4c1c1c0f8b6f7b8b2", -"a2b0a9a9b3d2c5c7d2e6c4e2d6d7e3d1c2e3c8c9d7d8d4c6c6c9c8c2c5c2c4d1c4c3d7c2c1c1e5c0c5c5c6c1e3e6e3c1c1c3f5e6c5c8d4c3c7c6d5c3b9c5b9e1e1c4g2c1c4c1b9c1c4c4c6c2c5c9c0d4c1c0f6d4e6g6d2e2d2e6d8d5e6d6f5f6f9d9e3c5e2d2c5c7d2e6c4e2d6d7e3d1c2e3c8c9d7d8d4c6c6c9c8c2c5c2c4d1c4c3d7c2c1c1e5c0c5c5c6c1e3e6e3c1c1c3f5e6c5c8d4c3c7c6d5c3b9c5b9e1e1c4g2c1c4c1b9c1c4c4c6c2c5c9c0d4c1c0f6d4e6g6d2e2d2e6d8d5e6d6f5f6f9d9e3c5e2d2c5c7d2e6c4e2d6d7e3d1c2e3c8c9d7d8d4c6c6c9c8c2c5c2c4d1c4c3d7c2c1c1e5c0c5c5c6c1e3e6e3c1c1c3f5e6c5c8d4c3c7c6d5c3b9c5b9e1e1c4g2c1c4c1b9c1c4c4c6c2c5c9c0d4c1c0f6d4e6g6d2e2d2e6d8d5e6d6f5f6f9d9e3c5e2d2c5c7d2e6c4e2d6d7e3d1c2e3c8c9d7d8d4c6c6c9c8c2c5c2c4d1c4c3d7c2c1c1e5c0c5c5c6c1e3e6e3c1c1c3f5e6c5c8d4c3c7c6d5c3b9c5b9e1e1c4g2c1c4c1b9c1c4c4c6b8b8f0f8b2", -"a2a8a9a9b7c5c7c9c9c9d9e4c7c5c6c1c3c2d6e3d7d5c1d7d7c8d6c8e7e6c5d5e6d1c6d6d0c1c0c1c2e3c4c0c6d7d6c6c3c4g2d7c5c6g2d4c8d7f6e1f2c4c3i3c1d5c4c5c5c3d5c4e4c5e6d9e5c9c1c3e6c0f6f6d6d2d2f2d2f5d8e6f2e4d5d5f9e7c5d7e4c5c7c9c9c9d9e4c7c5c6c1c3c2d6e3d7d5c1d7d7c8d6c8e7e6c5d5e6d1c6d6d0c1c0c1c2e3c4c0c6d7d6c6c3c4g2d7c5c6g2d4c8d7f6e1f2c4c3i3c1d5c4c5c5c3d5c4e4c5e6d9e5c9c1c3e6c0f6f6d6d2d2f2d2f5d8e6f2e4d5d5f9e7c5d7e4c5c7c9c9c9d9e4c7c5c6c1c3c2d6e3d7d5c1d7d7c8d6c8e7e6c5d5e6d1c6d6d0c1c0c1c2e3c4c0c6d7d6c6c3c4g2d7c5c6g2d4c8d7f6e1f2c4c3i3c1d5c4c5c5c3d5c4e4c5e6d9e5c9c1c3e6c0f6f6d6d2d2f2d2f5d8e6f2e4d5d5f9e7c5d7e4c5c7c9c9c9d9e4c7c5c6c1c3c2d6e3d7d5c1d7d7c8d6c8e7e6c5d5e6d1c6d6d0c1c0c1c2e3c4c0c6d7d6c6c3c4g2d7c5c6g2d4c8d7f6e1f2c4c3i3c1d5c4c5c5c3d5c4e4c5c6f0b8b6b8b2", -"a2b0a9a8b3c5c7d4e5d9d9e4e4e6e5e6c1e3c7c5e6c8c8c1c1c8c8e5e5d8f5c4c2d7d6c7d0c4d5c5d7e3c6c5c1d0d5c3d4d5c5c2g2e6c0e0c6f6g2e6c5d5e1g2c4c2c1c4c2c5b9c4d7b9c2c5e6c6c2d0d1c0c4c6e7c5e6c1c2g3e1e5d2g6d8f5f9d9c2d7d7d7c8d4e5d9d9e4e4e6e5e6c1e3c7c5e6c8c8c1c1c8c8e5e5d8f5c4c2d7d6c7d0c4d5c5d7e3c6c5c1d0d5c3d4d5c5c2g2e6c0e0c6f6g2e6c5d5e1g2c4c2c1c4c2c5b9c4d7b9c2c5e6c6c2d0d1c0c4c6e7c5e6c1c2g3e1e5d2g6d8f5f9d9c2d7d7d7c8d4e5d9d9e4e4e6e5e6c1e3c7c5e6c8c8c1c1c8c8e5e5d8f5c4c2d7d6c7d0c4d5c5d7e3c6c5c1d0d5c3d4d5c5c2g2e6c0e0c6f6g2e6c5d5e1g2c4c2c1c4c2c5b9c4d7b9c2c5e6c6c2d0d1c0c4c6e7c5e6c1c2g3e1e5d2g6d8f5f9d9c2d7d7d7c8d4e5d9d9e4e4e6e5e6c1e3c7c5e6c8c8c1c1c8c8e5e5d8f5c4c2d7d6c7d0c4d5c5d7e3c6c5c1d0d5c3d4d5c5c2g2e6c0e0c6f6g2e6c5d5e1g2c4c2c1c4c2c5b9c4d7b9c2b6b8b8b8b2", -"a2a8a9a8b3c4b9d4f6c7d9g6g6c9d7c2d7c2d7e6c4c6e5c1e5d3e3c6e1e1f5c2e6d6e7d6d1c3c1e3c2e6c5c6c1d4f6d5c3e6c1e5e1d4d7c3d0d1d4c2c1e1e1c2c5c4c1c4c5b9c0c5c5b9e5c5d9e5e6d1c6e5c1c1b9c8c4e5c1d8f5g6d2c2d8d5d2c8c2c7e6e5b9d4f6c7d9g6g6c9d7c2d7c2d7e6c4c6e5c1e5d3e3c6e1e1f5c2e6d6e7d6d1c3c1e3c2e6c5c6c1d4f6d5c3e6c1e5e1d4d7c3d0d1d4c2c1e1e1c2c5c4c1c4c5b9c0c5c5b9e5c5d9e5e6d1c6e5c1c1b9c8c4e5c1d8f5g6d2c2d8d5d2c8c2c7e6e5b9d4f6c7d9g6g6c9d7c2d7c2d7e6c4c6e5c1e5d3e3c6e1e1f5c2e6d6e7d6d1c3c1e3c2e6c5c6c1d4f6d5c3e6c1e5e1d4d7c3d0d1d4c2c1e1e1c2c5c4c1c4c5b9c0c5c5b9e5c5d9e5e6d1c6e5c1c1b9c8c4e5c1d8f5g6d2c2d8d5d2c8c2c7e6e5b9d4f6c7d9g6g6c9d7c2d7c2d7e6c4c6e5c1e5d3e3c6e1e1f5c2e6d6e7d6d1c3c1e3c2e6c5c6c1d4f6d5c3e6c1e5e1d4d7c3d0d1d4c2c1e1e1c2c5c4c1c4c5b9c0c5c5b9e5b8f7b8e8b2", -"a2a8a8a8b3c7e7d5e5b9d9g6f2f2f2d7d7d6c1d7c4c3e5c3e4b9c7e5e0g2g2e6c7d7d6c6c3e6d0c5c1c0c2e6c3c4d5c3d4c1c6g2e1e0c2f5c3c1g3d7d1e1c4b9c4c5c5b9c4c2c5b9c4e2b9c5c6c5d1d1c9c5c5d7d6d7d6c1e6d5d0e4d2d1c3c6g6c7c7d7c5c7e7d5e5b9d9g6f2f2f2d7d7d6c1d7c4c3e5c3e4b9c7e5e0g2g2e6c7d7d6c6c3e6d0c5c1c0c2e6c3c4d5c3d4c1c6g2e1e0c2f5c3c1g3d7d1e1c4b9c4c5c5b9c4c2c5b9c4e2b9c5c6c5d1d1c9c5c5d7d6d7d6c1e6d5d0e4d2d1c3c6g6c7c7d7c5c7e7d5e5b9d9g6f2f2f2d7d7d6c1d7c4c3e5c3e4b9c7e5e0g2g2e6c7d7d6c6c3e6d0c5c1c0c2e6c3c4d5c3d4c1c6g2e1e0c2f5c3c1g3d7d1e1c4b9c4c5c5b9c4c2c5b9c4e2b9c5c6c5d1d1c9c5c5d7d6d7d6c1e6d5d0e4d2d1c3c6g6c7c7d7c5c7e7d5e5b9d9g6f2f2f2d7d7d6c1d7c4c3e5c3e4b9c7e5e0g2g2e6c7d7d6c6c3e6d0c5c1c0c2e6c3c4d5c3d4c1c6g2e1e0c2f5c3c1g3d7d1e1c4b9c4c5c5b9c4c2c5b9c4e2b9b8b8b8g0b2", -"a2b0a8b0b3e6e3e6d7d6f3g6b9e7d6d7d7d7c2c1f6f6d1d1c0d9c5e1d8e0d0c7d4f6c1c4e6c5c1e3d5e5e6d5g3d5c4e5c0c2e6e0d8d5e0c8d9d7c2c9e0c4c2b9c4c5c4c2c4c5b9c4c5b9c7e5c5e5c6b9d6c5e6b9c6e3c1d0c2g6e7e4e5c1d5e3f2e7e7d9c7e6e3e6d7d6f3g6b9e7d6d7d7d7c2c1f6f6d1d1c0d9c5e1d8e0d0c7d4f6c1c4e6c5c1e3d5e5e6d5g3d5c4e5c0c2e6e0d8d5e0c8d9d7c2c9e0c4c2b9c4c5c4c2c4c5b9c4c5b9c7e5c5e5c6b9d6c5e6b9c6e3c1d0c2g6e7e4e5c1d5e3f2e7e7d9c7e6e3e6d7d6f3g6b9e7d6d7d7d7c2c1f6f6d1d1c0d9c5e1d8e0d0c7d4f6c1c4e6c5c1e3d5e5e6d5g3d5c4e5c0c2e6e0d8d5e0c8d9d7c2c9e0c4c2b9c4c5c4c2c4c5b9c4c5b9c7e5c5e5c6b9d6c5e6b9c6e3c1d0c2g6e7e4e5c1d5e3f2e7e7d9c7e6e3e6d7d6f3g6b9e7d6d7d7d7c2c1f6f6d1d1c0d9c5e1d8e0d0c7d4f6c1c4e6c5c1e3d5e5e6d5g3d5c4e5c0c2e6e0d8d5e0c8d9d7c2c9e0c4c2b9c4c5c4c2c4c5b9c4c5b9c7b8b8e8b8b2", -"a2b0b0b0b7d4d4e6e3c9f2d9d7c4d7d1c7c5c2c2d1e5d4d5c2e5d1g3d8c6c9d1c3d5c1c6c1c1d1c0d5c0c6d5g2e0c1c6e3c6e5d5f1d5e0b9c8c5c2b9e1c2d7c5c4c2c1c1e5b9c4c4c5c4c9d3f4d2f9g6e6c2d6c7e6f5d4c1d2d2d6d2e5c6c8d7f9e2d9d2d6d4d4e6e3c9f2d9d7c4d7d1c7c5c2c2d1e5d4d5c2e5d1g3d8c6c9d1c3d5c1c6c1c1d1c0d5c0c6d5g2e0c1c6e3c6e5d5f1d5e0b9c8c5c2b9e1c2d7c5c4c2c1c1e5b9c4c4c5c4c9d3f4d2f9g6e6c2d6c7e6f5d4c1d2d2d6d2e5c6c8d7f9e2d9d2d6d4d4e6e3c9f2d9d7c4d7d1c7c5c2c2d1e5d4d5c2e5d1g3d8c6c9d1c3d5c1c6c1c1d1c0d5c0c6d5g2e0c1c6e3c6e5d5f1d5e0b9c8c5c2b9e1c2d7c5c4c2c1c1e5b9c4c4c5c4c9d3f4d2f9g6e6c2d6c7e6f5d4c1d2d2d6d2e5c6c8d7f9e2d9d2d6d4d4e6e3c9f2d9d7c4d7d1c7c5c2c2d1e5d4d5c2e5d1g3d8c6c9d1c3d5c1c6c1c1d1c0d5c0c6d5g2e0c1c6e3c6e5d5f1d5e0b9c8c5c2b9e1c2d7c5c4c2c1c1e5b9c4c4c5c4c9e9g4g1g4b2", -"a2b0a8b0a5d4d1c6c1e6f2d9c8c4c2c6c7d6e5d0f6d1e0c8c2e6f6d8e1b9c7d4d5d0c0c6d0c4d5c3e6c1e6f5d8c1c8e6d6e6c4e0d5e5d8c6d7c2c5d5c2c5b9c5c4c2c1c4c2c4c4c2c4e4e3d2d2f4d2b9c6e6c9d7g3f5g3c9e5e6c9d3c7c5e5c9f2f4d7d6d4d4d1c6c1e6f2d9c8c4c2c6c7d6e5d0f6d1e0c8c2e6f6d8e1b9c7d4d5d0c0c6d0c4d5c3e6c1e6f5d8c1c8e6d6e6c4e0d5e5d8c6d7c2c5d5c2c5b9c5c4c2c1c4c2c4c4c2c4e4e3d2d2f4d2b9c6e6c9d7g3f5g3c9e5e6c9d3c7c5e5c9f2f4d7d6d4d4d1c6c1e6f2d9c8c4c2c6c7d6e5d0f6d1e0c8c2e6f6d8e1b9c7d4d5d0c0c6d0c4d5c3e6c1e6f5d8c1c8e6d6e6c4e0d5e5d8c6d7c2c5d5c2c5b9c5c4c2c1c4c2c4c4c2c4e4e3d2d2f4d2b9c6e6c9d7g3f5g3c9e5e6c9d3c7c5e5c9f2f4d7d6d4d4d1c6c1e6f2d9c8c4c2c6c7d6e5d0f6d1e0c8c2e6f6d8e1b9c7d4d5d0c0c6d0c4d5c3e6c1e6f5d8c1c8e6d6e6c4e0d5e5d8c6d7c2c5d5c2c5b9c5c4c2c1c4c2c4c4c2c4e4c5g1g4g4g4b2", -"a2b0b0a7a5c4d7c6c1d0e5d6c8e6c2c7c9e3c1c1d1d8c8c2e6f6d1c4c9g6d5d1e5e6c2c2c1d1c3d4c1c1c4c1g2c4c6d0c6c7e6f1c5b9c5c8c8c2e1e1c6c5c5c4c2c4d8c1c4c5c4b9c5d7c9e7d2d2d3c7c1c1d0c4d8d1f2c3f5d4c2e7b9e3d7c9e2d3c7d4d4c4d7c6c1d0e5d6c8e6c2c7c9e3c1c1d1d8c8c2e6f6d1c4c9g6d5d1e5e6c2c2c1d1c3d4c1c1c4c1g2c4c6d0c6c7e6f1c5b9c5c8c8c2e1e1c6c5c5c4c2c4d8c1c4c5c4b9c5d7c9e7d2d2d3c7c1c1d0c4d8d1f2c3f5d4c2e7b9e3d7c9e2d3c7d4d4c4d7c6c1d0e5d6c8e6c2c7c9e3c1c1d1d8c8c2e6f6d1c4c9g6d5d1e5e6c2c2c1d1c3d4c1c1c4c1g2c4c6d0c6c7e6f1c5b9c5c8c8c2e1e1c6c5c5c4c2c4d8c1c4c5c4b9c5d7c9e7d2d2d3c7c1c1d0c4d8d1f2c3f5d4c2e7b9e3d7c9e2d3c7d4d4c4d7c6c1d0e5d6c8e6c2c7c9e3c1c1d1d8c8c2e6f6d1c4c9g6d5d1e5e6c2c2c1d1c3d4c1c1c4c1g2c4c6d0c6c7e6f1c5b9c5c8c8c2e1e1c6c5c5c4c2c4d8c1c4c5c4b9c5d7c9f0g1g1f0b2", -"a2b0a6a6b1g4e9e9b6e8f0f0b8b8b8f0b8b8g0f8g0b8b8f8b5g0b5f0f0e9g0f8f0f8e8e8g0e8g0g0e8e8f8b8b5e8e8b6f8b6e8j2f0f0b8b8f0g0j3j3b8f0b8b8b8b5b8b8b8b8b8f8f0f0f0g1g1f0b6f8e8e8b8f8j2g0g1b8b8b8b8b8f0f0b6b6f0g1e8f8f8g4e9e9b6e8f0f0b8b8b8f0b8b8g0f8g0b8b8f8b5g0b5f0f0e9g0f8f0f8e8e8g0e8g0g0e8e8f8b8b5e8e8b6f8b6e8j2f0f0b8b8f0g0j3j3b8f0b8b8b8b5b8b8b8b8b8f8f0f0f0g1g1f0b6f8e8e8b8f8j2g0g1b8b8b8b8b8f0f0b6b6f0g1e8f8f8g4e9e9b6e8f0f0b8b8b8f0b8b8g0f8g0b8b8f8b5g0b5f0f0e9g0f8f0f8e8e8g0e8g0g0e8e8f8b8b5e8e8b6f8b6e8j2f0f0b8b8f0g0j3j3b8f0b8b8b8b5b8b8b8b8b8f8f0f0f0g1g1f0b6f8e8e8b8f8j2g0g1b8b8b8b8b8f0f0b6b6f0g1e8f8f8g4e9e9b6e8f0f0b8b8b8f0b8b8g0f8g0b8b8f8b5g0b5f0f0e9g0f8f0f8e8e8g0e8g0g0e8e8f8b8b5e8e8b6f8b6e8j2f0f0b8b8f0g0j3j3b8f0b8b8b8b5b8b8b8b8b8f8f0f0f0b2g1f0b6b2", -"a2b0a7b1b4f0g1e9f0b8f0g1b6b8b6b8b6j3g0b8j3b8f8b6g0f8g0f7f0f8b5j2b6b6b6e8g0f8f8e8e8g0e8f8e8b8b6g0b6b6b6j2j2b8f0f8g0b5j3g0e8f8e9b6b8f8f0f0f8f8b8b6b8e9f7f7f7f7b8b8e8b8b6b6e8e8g1g0g0f0b8b8b6b6b6b6f0f0f8f8b6g1g1e9f0b8f0g1b6b8b6b8b6j3g0b8j3b8f8b6g0f8g0f7f0f8b5j2b6b6b6e8g0f8f8e8e8g0e8f8e8b8b6g0b6b6b6j2j2b8f0f8g0b5j3g0e8f8e9b6b8f8f0f0f8f8b8b6b8e9f7f7f7f7b8b8e8b8b6b6e8e8g1g0g0f0b8b8b6b6b6b6f0f0f8f8b6g1g1e9f0b8f0g1b6b8b6b8b6j3g0b8j3b8f8b6g0f8g0f7f0f8b5j2b6b6b6e8g0f8f8e8e8g0e8f8e8b8b6g0b6b6b6j2j2b8f0f8g0b5j3g0e8f8e9b6b8f8f0f0f8f8b8b6b8e9f7f7f7f7b8b8e8b8b6b6e8e8g1g0g0f0b8b8b6b6b6b6f0f0f8f8b6g1g1e9f0b8f0g1b6b8b6b8b6j3g0b8j3b8f8b6g0f8g0f7f0f8b5j2b6b6b6e8g0f8f8e8e8g0e8f8e8b8b6g0b6b6b6j2j2b8f0f8g0b5j3g0e8f8e9b6b8f8f0f0f8f8b8b6b8e9f7g1b2f0b8b2", -"a1a6b1b4g0b6b5b8e9b5b6b6b8f0b8b8f8j2b8b8f8b5e8b6f8b5f0f7f0f7j2b5g0b8e8b8b8e8g0b8f8e8f8f0b5b6f0e8b8b6j2b6g0b6f8b8b5b4g0f7f8g1b8f0b6f0f7b8b5b8f7b8b6b6g1e9g1f0b6e9f0e9e8b6f8b6g1f8e8e9b8f0e8e8b6b6b6g0g0g0g0b8b5b8e9b5b6b6b8f0b8b8f8j2b8b8f8b5e8b6f8b5f0f7f0f7j2b5g0b8e8b8b8e8g0b8f8e8f8f0b5b6f0e8b8b6j2b6g0b6f8b8b5b4g0f7f8g1b8f0b6f0f7b8b5b8f7b8b6b6g1e9g1f0b6e9f0e9e8b6f8b6g1f8e8e9b8f0e8e8b6b6b6g0g0g0g0b8b5b8e9b5b6b6b8f0b8b8f8j2b8b8f8b5e8b6f8b5f0f7f0f7j2b5g0b8e8b8b8e8g0b8f8e8f8f0b5b6f0e8b8b6j2b6g0b6f8b8b5b4g0f7f8g1b8f0b6f0f7b8b5b8f7b8b6b6g1e9g1f0b6e9f0e9e8b6f8b6g1f8e8e9b8f0e8e8b6b6b6g0g0g0g0b8b5b8e9b5b6b6b8f0b8b8f8j2b8b8f8b5e8b6f8b5f0f7f0f7j2b5g0b8e8b8b8e8g0b8f8e8f8f0b5b6f0e8b8b6j2b6g0b6f8b8b5b4g0f7f8g1b8f0b6f0f7b8b5b8f7b8b6b6g1e9g1b2b6b2", -"a2b1a0j2e8e8f8b8b8b8f8b8b8b6b8b6b8g0b8b8b5b6b6f8f8f8g1e9g1g1j2b5b5f7f0g0g0b8g0e8b6b8b8b6f8b6f0b6b5b8b8f8b8e8e8f8j2j3b8b8f0g1b6f8b6g1b8g0f8b8f0f0f7b8b6e9g1e9f7f7e9e8f0e8g0b5g1f8e8g1b6b6b6b6b6b6g0j2b5f8e8b8f8b8b8b8f8b8b8b6b8b6b8g0b8b8b5b6b6f8f8f8g1e9g1g1j2b5b5f7f0g0g0b8g0e8b6b8b8b6f8b6f0b6b5b8b8f8b8e8e8f8j2j3b8b8f0g1b6f8b6g1b8g0f8b8f0f0f7b8b6e9g1e9f7f7e9e8f0e8g0b5g1f8e8g1b6b6b6b6b6b6g0j2b5f8e8b8f8b8b8b8f8b8b8b6b8b6b8g0b8b8b5b6b6f8f8f8g1e9g1g1j2b5b5f7f0g0g0b8g0e8b6b8b8b6f8b6f0b6b5b8b8f8b8e8e8f8j2j3b8b8f0g1b6f8b6g1b8g0f8b8f0f0f7b8b6e9g1e9f7f7e9e8f0e8g0b5g1f8e8g1b6b6b6b6b6b6g0j2b5f8e8b8f8b8b8b8f8b8b8b6b8b6b8g0b8b8b5b6b6f8f8f8g1e9g1g1j2b5b5f7f0g0g0b8g0e8b6b8b8b6f8b6f0b6b5b8b8f8b8e8e8f8j2j3b8b8f0g1b6f8b6g1b8g0f8b8f0f0f7b8b6e9g1e9b2b2", -"a4i4i4b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2i4b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2i4b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2i4b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2i4b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2i2", -}; diff -r f427b8ec4379 -r 41ff10fd062f lib-src/ChangeLog --- a/lib-src/ChangeLog Mon Aug 13 10:03:54 2007 +0200 +++ b/lib-src/ChangeLog Mon Aug 13 10:04:58 2007 +0200 @@ -1,3 +1,13 @@ +1997-11-02 SL Baur + + * update-custom.sh (dirs): Remove packaged directories. + + * update-elc.sh (ignore_pattern): Hyperbole, oobr and ilisp are + now packaged. + + * update-autoloads.sh (mule_p): Hyperbole and oobr are now + packaged. + 1997-10-30 SL Baur * update-autoloads.sh (mule_p): EFS has been packaged. diff -r f427b8ec4379 -r 41ff10fd062f lib-src/update-autoloads.sh --- a/lib-src/update-autoloads.sh Mon Aug 13 10:03:54 2007 +0200 +++ b/lib-src/update-autoloads.sh Mon Aug 13 10:04:58 2007 +0200 @@ -94,9 +94,11 @@ # EFS is now packaged #make_special efs autoloads #make_special eos autoloads # EOS doesn't have custom or autoloads -make_special hyperbole autoloads +# Hyperbole is now packaged +# make_special hyperbole autoloads # make_special ilisp autoloads -make_special oobr HYPB_ELC='' autoloads +# oobr is now packaged +# make_special oobr HYPB_ELC='' autoloads ## W3 is a package now ##make_special w3 autoloads diff -r f427b8ec4379 -r 41ff10fd062f lib-src/update-custom.sh --- a/lib-src/update-custom.sh Mon Aug 13 10:03:54 2007 +0200 +++ b/lib-src/update-custom.sh Mon Aug 13 10:04:58 2007 +0200 @@ -65,8 +65,8 @@ # These directories don't have customizations, or are partially broken. # If some of the packages listed here are customized, don't forget to # remove the directory! -ignore_dirs="cl egg eos ilisp its language locale mel mu sunpro term \ -tooltalk iso mailcrypt oobr tl tm mh-e hyperbole electric apel \ +ignore_dirs="cl egg eos its language locale sunpro term \ +tooltalk iso electric \ hm--html-menus gnats pcl-cvs vm" # Only use Mule XEmacs to build Mule-specific autoloads & custom-loads. diff -r f427b8ec4379 -r 41ff10fd062f lib-src/update-elc.sh --- a/lib-src/update-elc.sh Mon Aug 13 10:03:54 2007 +0200 +++ b/lib-src/update-elc.sh Mon Aug 13 10:04:58 2007 +0200 @@ -106,8 +106,8 @@ # first recompile the byte-compiler, so that the other compiles take place # with the latest version (assuming we're compiling the lisp dir of the emacs # we're running, which might not be the case, but often is.) -echo "Checking the byte compiler..." -$BYTECOMP -f batch-byte-recompile-directory lisp/bytecomp +#echo "Checking the byte compiler..." +#$BYTECOMP -f batch-byte-recompile-directory lisp/bytecomp # Prepare for byte-compiling directories with directory-specific instructions make_special_commands='' @@ -131,11 +131,14 @@ # make_special efs x20 make_special eos -k # not strictly necessary... ## make_special gnus some # Now this is a package. -make_special hyperbole elc +# hyperbole is now packaged +# make_special hyperbole elc # We're not ready for the following, yet. #make_special ilisp XEmacsELC=custom-load.elc elc -make_special ilisp elc -make_special oobr HYPB_ELC='' elc +# ilisp is now packaged +# make_special ilisp elc +# oobr is now packaged +# make_special oobr HYPB_ELC='' elc ## W3 is a package now. #make_special w3 xemacs-w3 diff -r f427b8ec4379 -r 41ff10fd062f lisp/ChangeLog --- a/lisp/ChangeLog Mon Aug 13 10:03:54 2007 +0200 +++ b/lisp/ChangeLog Mon Aug 13 10:04:58 2007 +0200 @@ -1,3 +1,476 @@ +1997-11-08 SL Baur + + * prim/about.el (about-hackers): New entries. + + * utils/shadow.el (list-load-path-shadows): Supress message when + no shadowings are found. + + * loadup.el: Modify algorithm for finding initial lisp directories + since the search now starts from lisp/ not lisp/prim/. + * update-elc.el: Ditto. + * make-docfile.el: Ditto. + +1997-11-07 SL Baur + + * prim/dumped-lisp.el: "lib-complete" is not dumped with InfoDock. + * utils/finder.el (finder-known-keywords): New keyword -- `dumped'. + + * version.el: Cleaned up Lisp comments. + * paths.el: Ditto. + * x-menubar.el: Ditto. + * x-faces.el: Ditto. + * x-iso8859-1.el: Ditto. + * x-mouse.el: Ditto. + * x-select.el: Ditto. + * x-scrollbar.el: Ditto. + * x-misc.el: Ditto. + * x-init.el: Ditto. + * x-toolbar.el: Ditto. + + * backquote.el: Moved to top-level. Cleaned up Lisp comments. + * packages.el: Ditto. + * subr.el: Ditto. + * replace.el: Ditto. + * cl.el: Ditto. + * cl-extra.el: Ditto. + * cl-seq.el: Ditto. + * widget.el: Ditto. + * custom.el: Ditto. + * cus-start.el: Ditto. + * cmdloop.el: Ditto. + * keymap.el: Ditto. + * syntax.el: Ditto. + * device.el: Ditto. + * console.el: Ditto. + * obsolete.el: Ditto. + * specifier.el: Ditto. + * faces.el: Ditto. + * glyphs.el: Ditto. + * objects.el: Ditto. + * extents.el: Ditto. + * events.el: Ditto. + * text-props.el: Ditto. + * process.el: Ditto. + * frame.el: Ditto. + * map-ynp.el: Ditto. + * simple.el: Ditto. + * keydefs.el: Ditto. + * abbrev.el: Ditto. + * derived.el: Ditto. + * minibuf.el: Ditto. + * list-mode.el: Ditto. + * modeline.el: Ditto. + * startup.el: Ditto. + * misc.el: Ditto. + * help-nomule.el: Ditto. + * help.el: Ditto. + * files-nomule.el: Ditto. + * files.el: Ditto. + * lib-complete.el: Ditto. + * format.el: Ditto. + * indent.el: Ditto. + * isearch-mode.el: Ditto. + * buffer.el: Ditto. + * buff-menu.el: Ditto. + * undo-stack.el: Ditto. + * window.el: Ditto. + * window-xemacs.el: Ditto. + * lisp.el: Ditto. + * page.el: Ditto. + * register.el: Ditto. + * iso8859-1.el: Ditto. + * paragraphs.el: Ditto. + * easymenu.el: Ditto. + * lisp-mode.el: Ditto. + * text-mode.el: Ditto. + * fill.el: Ditto. + * auto-save.el: Ditto. + * float-sup.el: Ditto. + * itimer.el: Ditto. + * itimer-autosave.el: Ditto. + * toolbar.el: Ditto. + * scrollbar.el: Ditto. + * menubar.el: Ditto. + * dialog.el: Ditto. + * gui.el: Ditto. + * mode-motion.el: Ditto. + * mouse.el: Ditto. + * tty-init.el: Ditto. + * auto-show.el: Ditto. + +1997-11-07 Kyle Jones + + * modes/abbrev.el (abbrev-prefix-mark): Instead of + inserting a dash to indicate the start of the abbrev, + add an extent with a begin-glyph that contains a dash. + +Wed Nov 05 23:40:00 1997 Jonathan Harris + + * faces.el: init-other-random-faces + Reinstated code that uses (mono x) as a specifer tag, but + conditioned it on (featurep 'x) because x is not a valid + specifier tag under native-win32. + + * Added file headers to: + w32-faces.el, w32-init.el + +Sun Nov 01 12:00:00 1997 Jonathan Harris + + * make-docfile.el: Fixed typo when dumped file does not exist. + + * device.el: make-w32-device added. + + * dumped-lisp: added w32-faces and w32-init to list. + + * faces.el: + - make-face-*: Added calls to appropriate w32 functions + conditioned on (featurep 'w32). Made existing X calls + conditioned on (featurep 'x). + - init-other-random-faces: Hacked out a piece of code which used + (mono x) as a specifier because it made w32 unhappy. + + * New files: + w32-faces.el, w32-init.el + +1997-11-07 Hrvoje Niksic + + * prim/mouse.el (default-mouse-motion-handler): When over + modeline, correctly dehighlight the last extent. + +1997-11-07 Hrvoje Niksic + + * prim/minibuf.el (mouse-read-file-name-1): Ditto. + + * packages/balloon-help.el (balloon-help-make-help-frame): Ditto. + + * games/life.el (life-setup): Check for scrollbars before using + them. + +1997-11-07 Hrvoje Niksic + + * hm--html-menus/hm--html-mode.el (hm--html-minor-mode): Ditto. + + * hm--html-menus/hm--html-menu.el ((adapt-xemacsp)): Ditto. + + * comint/gud.el (gdb-install-menubar): Ditto. + + * calendar/calendar.el (calendar-mode): Ditto. + + * auctex/bib-cite.el (bib-cite-initialize): Ditto. + + * utils/floating-toolbar.el (floating-toolbar): Ditto. + + * utils/edit-toolbar.el (edit-toolbar-mode): Ditto. + + * utils/browse-cltl2.el (cltl2-lisp-mode-install): Ditto. + + * modes/view-process-xemacs.el + (View-process-install-pulldown-menu): Ditto. + + * modes/verilog-mode.el (verilog-mode): Ditto. + + * modes/tcl.el (tcl-mode): Ditto. + + * modes/f90.el (f90-mode): Ditto. + + * packages/emerge.el (emerge-set-keys): Ditto. + + * packages/tar-mode.el (tar-mode): Check for menubars. + +1997-11-07 Kyle Jones + + * lisp/prim/modeline.el (mouse-drag-modeline): Don't + allow the window size to shrink to a size that is not a + multiple of the height of the default face's font. + + * lisp/prim/modeline.el (mouse-drag-modeline): Don't + discard timeout events. + +1997-11-07 SL Baur + + * prim/simple.el (universal-argument-minus): Retain zmacs region. + +1997-11-07 Hrvoje Niksic + + * packages/hyper-apropos.el (hyper-apropos-grok-functions): Ignore + errors when fetching documentation. + + * prim/about.el (about-maintainer-glyph): Handle not having XPM or + XBM gracefully. + + * custom/wid-edit.el (widget-glyph-find): Allow glyphs without + window-system, when TAG is nil. + +1997-11-05 Jens-Ulrik Holger Petersen + + * mule/mule-cmds.el (set-default-coding-systems): Make + add-hook to `comint-exec-hook' be an append, for when the user + changes language environment say. + +1997-11-05 SL Baur + + * prim/winnt.el: Use a cleaner method for getting Text/Binary file + type in the mode-line for MS Windows. + +1997-11-06 Hrvoje Niksic + + * prim/mouse.el: Removed "junk me" functions. + + * prim/mouse.el (default-mouse-motion-handler): Make events over + modeline invalidate `point'. + + * prim/mouse.el (mouse-line-length): Use point-at-eol and + point-at-bol. + (default-mouse-track-normalize-point): Highlight the whole symbol + only if the mouse is on a symbol-constituent. + + * custom/wid-edit.el (widget-specify-field): Make sure the extent + is end-open. + + * prim/keymap.el (next-key-event): Use `next-command-event'. + +1997-11-05 Hrvoje Niksic + + * utils/easymenu.el (easy-menu-add): Check with `equal' whether + the menu already belongs to all-popups. + +1997-11-05 Jan Vroonhof + + * packages/font-lock.el (font-lock-thing-lock-cleanup): + Provisionally add lazy-shot + + * modes/lazy-shot.el (lazy-shot-mode): Unstall lazy-shot only if + needed. + (lazy-shot-fontify-internal): Functionality put in seperate function. + (lazy-shot-lock-extent): Use it. + (lazy-shot-fontify-region): Dumb implementation added. + (lazy-shot-unstall-after-fontify): Needed to disable lazy + fontifying after fontify-buffer. + (lazy-shot-unstall): Make sure buffer is left in a fontified state if + needed. Take optional argument. + + + * packages/ps-print.el (ps-print-ensure-fontified): Added + temporary support for lazy-shot. + +1997-11-05 Hrvoje Niksic + + * utils/text-props.el (set-text-properties): Updated docstring. + +1997-11-04 Didier Verna + + * mule/mule-cmds.el (set-default-coding-systems): + The coding-system argument to comint-exec-hook wasn't evaluated + before building the lambda expression. + +1997-11-04 Jens-Ulrik Holger Petersen + + * packages/time.el: Change all occurences of ballon to balloon. + +1997-11-04 Jens-Ulrik Holger Petersen + + * prim/help.el (function-at-point-function): Remove this variable. + (function-at-point): Remove use of `function-at-point-function'. + + * packages/info.el (Info-elisp-ref): Change call to + `find-function-function' to `function-at-point'. + +1997-11-04 Jens-Ulrik Holger Petersen + + * packages/info.el (Info-elisp-ref): Really change call to + `find-function-function' to `function-at-point'. + +1997-11-04 Hrvoje Niksic + + * packages/auto-save.el: Updated commentary; changed default + autosave fallback to "~/.autosave". Minor changes to compile + without warnings. + +1997-11-03 Hrvoje Niksic + + * prim/subr.el (function-interactive): New function. + +1997-11-03 SL Baur + + * prim/dumped-lisp.el: Dump auto-save with XEmacs. + + * prim/loadup.el: Make sure top level lisp directory gets a + trailing slash when added to load-path. + * prim/make-docfile.el: Ditto. + +1997-11-03 MORIOKA Tomohiko + + * prim/simple.el (interprogram-cut-function, + interprogram-paste-function): New variable (imported from Emacs + 20.2). + (kill-new): Use `interprogram-cut-function' if it is not nil. + (current-kill): Use `interprogram-paste-function' if it is not + nil. + +1997-11-03 MORIOKA Tomohiko + + * locale/ja/locale-start.el (startup-splash-frame-body): Modify to + be more natural Japanese. + + * x11/x-menubar.el: Delete "language environment" menu of + "Options" menu. + +1997-11-02 MORIOKA Tomohiko + + * language/korean.el: Rename TUTORIAL.kr -> TUTORIAL.ko to fit + with ISO 639 (two letter language code). + + * prim/dumped-lisp.el: Don't dump language/vietnamese.el because + language/viet-util.el was removed temporary. + + * language/japanese.el: Rename TUTORIAL.jp -> TUTORIAL.ja to fit + with ISO 639 (two letter language code). + +1997-10-31 Pete Ware + + * shell.el (shell-chdrive-regexp): New for DOS/NT + (shell-mode): Added shell-font-lock-keywrods + (shell-mode): Use $PWD for ksh + (shell-directory-tracker): Use dirs and dirtrack-toggle. This may + cause problems at is interferes with "dired" + (shell-snarf-envar): NEW + (shell-copy-environment-variable): NEW + +1997-10-30 Pete Ware + + * comint.el (comint-mode-map): Rearranged menus so they have a + meaningful name. + +1997-10-30 Pete Ware + + * comint.el (comint-find-source-file-hook): + (comint-goto-source-line-hook): + (comint-find-source-code): + (comint-default-find-source-file): + (comint-fixup-source-file-name): + (comint-default-goto-source-line): Removed. compile.el does a + better job of this stuff. + + * comint.el + (comint-file-name-chars): Support for msdos/nt + - Let easymenu deal with whether menubar is available. + - Use ^d for delchar or maybe eof. + - Use "dumb" as the terminal type if on a system using terminfo + (comint-output-filter): Removed replacement of ^M -- use filter + (comint-dynamic-complete-as-filename): Don't set + file-name-handler-alist to nil. This makes remote path + completion work! + +1997-11-02 SL Baur + + * prim/advocacy.el (xemacs-praise-sound-file): Don't default to + using a hardcoded directory. + + * eterm/term.el (term-is-xemacs): Match against XEmacs instead of + Lucid. + + * eos/sun-eos-toolbar.el (eos::toolbar-icon-directory): Use + `locate-data-directory' instead of data-directory. + * eterm/term.el (term-exec-1): Ditto. + * packages/time.el (display-time-icons-dir): Ditto. + * prim/advocacy.el (praise-be-unto-xemacs): Ditto. + * prim/sound.el (default-sound-directory): Ditto. + * prim/toolbar.el (init-toolbar-location): Ditto. + +1997-10-31 Hrvoje Niksic + + * custom/wid-edit.el (widget-color-complete): Use + `read-color-completion-table' directly. + + * prim/subr.el (rplaca): Warn against the return value. + (replace-in-string): Use `wrong-type-argument'. Use standard + error message. + (functionp): Would bug out on certain types of objects; synch with + FSF. + (with-output-to-string): Use new-style backquotes. + (with-temp-buffer): Update docstring references. + + * prim/minibuf.el (reset-buffer): Use `with-current-buffer'. + (read-color-completion-table): Ditto. + (read-color-completion-table): Complete TTY colors on TTY devices. + + * custom/cus-start.el: Customize `scroll-conservatively'. + Customize `help-char' correctly. + +1997-11-02 SL Baur + + * packages/desktop.el (toplevel): Don't require dired or reporter + when byte compiling. + +1997-11-02 Hrvoje Niksic + + * prim/keymap.el (synthesize-keysym): Collect a list of + characters, instead of consing a string each time. + (synthesize-keysym): Better error checking. + + * prim/keymap.el (synthesize-keysym): Don't bug out when reading a + non-character event. + +1997-11-02 Tomasz Cholewo + + * prim/keymap.el (synthesize-keysym): New function bound to C-x @ k. + +1997-11-02 Kyle Jones + + * modes/sendmail.el: Don't (require 'vm-misc). Change + mail-do-fcc-vm-internal to not compile the chunk of code + that uses VM internal macros. This prevents the byte + compiler from compiling such references into function + calls that Fbyte_code will complain about later when it + discovers that the references are macros. + + * modes/sendmail.el: added defvars for + rmail-summary-buffer and rmail-total-messages to get + rid of compiler warnings. +1997-11-01 Hrvoje Niksic + + * prim/subr.el (lambda): Moved from `packages.el'. + + * prim/packages.el: Updated commentary. + (packages-useful-lisp): Added `cl-macs'. + +1997-10-27 Didier Verna + + * prim/help-nomule.el (help-with-tutorial): The 'didactic' blank + lines message is now taken directly from each tutorial, and thus + can appear in different languages. + + * mule/mule-help.el (help-with-tutorial): idem + +1997-10-26 Karl M. Hegbloom + + * utils/shadowfile.el (shadow-clusters): Customized. + (shadow-read-files): replace obsolete `eval-current-buffer' + (shadow-parse-fullpath): `efs-ftp-name' doesn't exist. change to + `efs-ftp-path' + +1997-11-01 SL Baur + + * x11/x-menubar.el: Change Viper menu item to use + `toggle-viper-mode'. + Suggested by Michael Kifer + + * mule/mule-init.el: Remove `help-with-tutorial-for-mule'. + Suggested by Didier Verna + + * Disable Cyrillic CCL until CCL engine gets fixed. + From: Martin Buchholz + +1997-10-30 Colin Rafferty + + * prim/startup.el (command-line-early): Made it recognize + --vanilla and --no-packages, as is already done in emacs.c. + +1997-10-30 Karl M. Hegbloom + + * modes/cperl-mode.el: Add Commentary and Code statements to + comment header for finder. + 1997-10-30 SL Baur * vm/vm-vars.el (vm-image-directory): Use locate-data-directory if diff -r f427b8ec4379 -r 41ff10fd062f lisp/abbrev.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/abbrev.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,535 @@ +;;; abbrev.el --- abbrev mode commands for Emacs + +;; Copyright (C) 1985, 1986, 1987, 1992, 1997 Free Software Foundation, Inc. + +;; Maintainer: XEmacs Development Team +;; Keywords: abbrev, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34 (With some additions) + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; This facility is documented in the Emacs Manual. + +;;; Code: + +;jwz: this is preloaded so don't ;;;###autoload +(defcustom only-global-abbrevs nil "\ +*Non-nil means user plans to use global abbrevs only. +Makes the commands to define mode-specific abbrevs define global ones instead." + :type 'boolean + :group 'abbrev) + +;;; XEmacs: the following block of code is not in FSF +(defvar abbrev-table-name-list '() + "List of symbols whose values are abbrev tables.") + +(defvar abbrevs-changed nil + "Set non-nil by defining or altering any word abbrevs. +This causes `save-some-buffers' to offer to save the abbrevs.") + +(defun make-abbrev-table () + "Create a new, empty abbrev table object." + (make-vector 59 0)) ; 59 is prime + +(defun clear-abbrev-table (table) + "Undefine all abbrevs in abbrev table TABLE, leaving it empty." + (fillarray table 0) + (setq abbrevs-changed t) + nil) + + +(defun define-abbrev-table (name defs) + "Define TABNAME (a symbol) as an abbrev table name. +Define abbrevs in it according to DEFINITIONS, which is a list of elements +of the form (ABBREVNAME EXPANSION HOOK USECOUNT)." + (let ((table (and (boundp name) (symbol-value name)))) + (cond ((vectorp table)) + ((not table) + (setq table (make-abbrev-table)) + (set name table) + (setq abbrev-table-name-list (cons name abbrev-table-name-list))) + (t + (setq table (signal 'wrong-type-argument (list 'vectorp table))) + (set name table))) + (while defs + (apply (function define-abbrev) table (car defs)) + (setq defs (cdr defs))))) + +(defun define-abbrev (table name &optional expansion hook count) + "Define an abbrev in TABLE named NAME, to expand to EXPANSION or call HOOK. +NAME and EXPANSION are strings. Hook is a function or `nil'. +To undefine an abbrev, define it with an expansion of `nil'." + (or (not expansion) + (stringp expansion) + (setq expansion (signal 'wrong-type-argument + (list 'stringp expansion)))) + (or (not count) + (integerp count) + (setq count (signal 'wrong-type-argument + (list 'fixnump count)))) + (or (vectorp table) + (setq table (signal 'wrong-type-argument + (list 'vectorp table)))) + (let* ((sym (intern name table)) + (oexp (and (boundp sym) (symbol-value sym))) + (ohook (and (fboundp sym) (symbol-function sym)))) + (unless (and (equal ohook hook) + (stringp oexp) + (stringp expansion) + (string-equal oexp expansion)) + (setq abbrevs-changed t) + ;; If there is a non-word character in the string, set the flag. + (if (string-match "\\W" name) + (set (intern " " table) nil))) + (set sym expansion) + (fset sym hook) + (setplist sym (or count 0)) + name)) + + +;; Fixup stuff from bootstrap def of define-abbrev-table in subr.el +(let ((l abbrev-table-name-list)) + (while l + (let ((fixup (car l))) + (if (consp fixup) + (progn + (setq abbrev-table-name-list (delq fixup abbrev-table-name-list)) + (define-abbrev-table (car fixup) (cdr fixup)))) + (setq l (cdr l)))) + ;; These are no longer initialised by C code + (if (not global-abbrev-table) + (progn + (setq global-abbrev-table (make-abbrev-table)) + (setq abbrev-table-name-list (cons 'global-abbrev-table + abbrev-table-name-list)))) + (if (not fundamental-mode-abbrev-table) + (progn + (setq fundamental-mode-abbrev-table (make-abbrev-table)) + (setq abbrev-table-name-list (cons 'fundamental-mode-abbrev-table + abbrev-table-name-list)))) + (and (eq major-mode 'fundamental-mode) + (not local-abbrev-table) + (setq local-abbrev-table fundamental-mode-abbrev-table))) + + +(defun define-global-abbrev (name expansion) + "Define ABBREV as a global abbreviation for EXPANSION." + (interactive "sDefine global abbrev: \nsExpansion for %s: ") + (define-abbrev global-abbrev-table + (downcase name) expansion nil 0)) + +(defun define-mode-abbrev (name expansion) + "Define ABBREV as a mode-specific abbreviation for EXPANSION." + (interactive "sDefine mode abbrev: \nsExpansion for %s: ") + (define-abbrev (or local-abbrev-table + (error "Major mode has no abbrev table")) + (downcase name) expansion nil 0)) + +(defun abbrev-symbol (abbrev &optional table) + "Return the symbol representing abbrev named ABBREV. +This symbol's name is ABBREV, but it is not the canonical symbol of that name; +it is interned in an abbrev-table rather than the normal obarray. +The value is nil if that abbrev is not defined. +Optional second arg TABLE is abbrev table to look it up in. +The default is to try buffer's mode-specific abbrev table, then global table." + (let ((frob (function (lambda (table) + (let ((sym (intern-soft abbrev table))) + (if (and (boundp sym) + (stringp (symbol-value sym))) + sym + nil)))))) + (if table + (funcall frob table) + (or (and local-abbrev-table + (funcall frob local-abbrev-table)) + (funcall frob global-abbrev-table))))) + +(defun abbrev-expansion (abbrev &optional table) + "Return the string that ABBREV expands into in the current buffer. +Optionally specify an abbrev table as second arg; +then ABBREV is looked up in that table only." + (let ((sym (abbrev-symbol abbrev table))) + (if sym + (symbol-value sym) + nil))) + +(defun unexpand-abbrev () + "Undo the expansion of the last abbrev that expanded. +This differs from ordinary undo in that other editing done since then +is not undone." + (interactive) + (if (or (< last-abbrev-location (point-min)) + (> last-abbrev-location (point-max)) + (not (stringp last-abbrev-text))) + nil + (let* ((opoint (point)) + (val (symbol-value last-abbrev)) + (adjust (length val))) + ;; This isn't correct if (symbol-function last-abbrev-text) + ;; was used to do the expansion + (goto-char last-abbrev-location) + (delete-region last-abbrev-location (+ last-abbrev-location adjust)) + (insert last-abbrev-text) + (setq adjust (- adjust (length last-abbrev-text))) + (setq last-abbrev-text nil) + (if (< last-abbrev-location opoint) + (goto-char (- opoint adjust)) + (goto-char opoint))))) + + + +(defun insert-abbrev-table-description (name human-readable) + "Insert before point a full description of abbrev table named NAME. +NAME is a symbol whose value is an abbrev table. +If optional 2nd arg HUMAN is non-nil, insert a human-readable description. +Otherwise the description is an expression, +a call to `define-abbrev-table', which would +define the abbrev table NAME exactly as it is currently defined." + (let ((table (symbol-value name)) + (stream (current-buffer))) + (message "Abbrev-table %s..." name) + (if human-readable + (progn + (prin1 (list name) stream) + ;; Need two terpri's or cretinous edit-abbrevs blows out + (terpri stream) + (terpri stream) + (mapatoms (function (lambda (sym) + (if (symbol-value sym) + (let* ((n (prin1-to-string (symbol-name sym))) + (pos (length n))) + (princ n stream) + (while (< pos 14) + (write-char ?\ stream) + (setq pos (1+ pos))) + (princ (format " %-5S " (symbol-plist sym)) + stream) + (if (not (symbol-function sym)) + (prin1 (symbol-value sym) stream) + (progn + (setq n (prin1-to-string (symbol-value sym)) + pos (+ pos 6 (length n))) + (princ n stream) + (while (< pos 45) + (write-char ?\ stream) + (setq pos (1+ pos))) + (prin1 (symbol-function sym) stream))) + (terpri stream))))) + table) + (terpri stream)) + (progn + (princ "\(define-abbrev-table '" stream) + (prin1 name stream) + (princ " '\(\n" stream) + (mapatoms (function (lambda (sym) + (if (symbol-value sym) + (progn + (princ " " stream) + (prin1 (list (symbol-name sym) + (symbol-value sym) + (symbol-function sym) + (symbol-plist sym)) + stream) + (terpri stream))))) + table) + (princ " \)\)\n" stream))) + (terpri stream)) + (message "")) +;;; End code not in FSF + +(defun abbrev-mode (arg) + "Toggle abbrev mode. +With argument ARG, turn abbrev mode on iff ARG is positive. +In abbrev mode, inserting an abbreviation causes it to expand +and be replaced by its expansion." + (interactive "P") + (setq abbrev-mode + (if (null arg) (not abbrev-mode) + (> (prefix-numeric-value arg) 0))) + ;; XEmacs change + (redraw-modeline)) + + +(defvar edit-abbrevs-map nil + "Keymap used in edit-abbrevs.") +(if edit-abbrevs-map + nil + (setq edit-abbrevs-map (make-sparse-keymap)) + ;; XEmacs change + (set-keymap-name edit-abbrevs-map 'edit-abbrevs-map) + (define-key edit-abbrevs-map "\C-x\C-s" 'edit-abbrevs-redefine) + (define-key edit-abbrevs-map "\C-c\C-c" 'edit-abbrevs-redefine)) + +(defun kill-all-abbrevs () + "Undefine all defined abbrevs." + (interactive) + (let ((tables abbrev-table-name-list)) + (while tables + (clear-abbrev-table (symbol-value (car tables))) + (setq tables (cdr tables))))) + +(defun insert-abbrevs () + "Insert after point a description of all defined abbrevs. +Mark is set after the inserted text." + (interactive) + (push-mark + (save-excursion + (let ((tables abbrev-table-name-list)) + (while tables + (insert-abbrev-table-description (car tables) t) + (setq tables (cdr tables)))) + (point)))) + +(defun list-abbrevs () + "Display a list of all defined abbrevs." + (interactive) + (display-buffer (prepare-abbrev-list-buffer))) + +(defun prepare-abbrev-list-buffer () + (save-excursion + (set-buffer (get-buffer-create "*Abbrevs*")) + (erase-buffer) + (let ((tables abbrev-table-name-list)) + (while tables + (insert-abbrev-table-description (car tables) t) + (setq tables (cdr tables)))) + (goto-char (point-min)) + (set-buffer-modified-p nil) + (edit-abbrevs-mode)) + (get-buffer-create "*Abbrevs*")) + +(defun edit-abbrevs-mode () + "Major mode for editing the list of abbrev definitions. +\\{edit-abbrevs-map}" + (interactive) + (setq major-mode 'edit-abbrevs-mode) + (setq mode-name "Edit-Abbrevs") + (use-local-map edit-abbrevs-map)) + +(defun edit-abbrevs () + "Alter abbrev definitions by editing a list of them. +Selects a buffer containing a list of abbrev definitions. +You can edit them and type \\\\[edit-abbrevs-redefine] to redefine abbrevs +according to your editing. +Buffer contains a header line for each abbrev table, + which is the abbrev table name in parentheses. +This is followed by one line per abbrev in that table: +NAME USECOUNT EXPANSION HOOK +where NAME and EXPANSION are strings with quotes, +USECOUNT is an integer, and HOOK is any valid function +or may be omitted (it is usually omitted)." + (interactive) + (switch-to-buffer (prepare-abbrev-list-buffer))) + +(defun edit-abbrevs-redefine () + "Redefine abbrevs according to current buffer contents." + (interactive) + (define-abbrevs t) + (set-buffer-modified-p nil)) + +(defun define-abbrevs (&optional arg) + "Define abbrevs according to current visible buffer contents. +See documentation of `edit-abbrevs' for info on the format of the +text you must have in the buffer. +With argument, eliminate all abbrev definitions except +the ones defined from the buffer now." + (interactive "P") + (if arg (kill-all-abbrevs)) + (save-excursion + (goto-char (point-min)) + (while (and (not (eobp)) (re-search-forward "^(" nil t)) + (let* ((buf (current-buffer)) + (table (read buf)) + abbrevs name hook exp count) + (forward-line 1) + (while (progn (forward-line 1) + (not (eolp))) + (setq name (read buf) count (read buf) exp (read buf)) + (skip-chars-backward " \t\n\f") + (setq hook (if (not (eolp)) (read buf))) + (skip-chars-backward " \t\n\f") + (setq abbrevs (cons (list name exp hook count) abbrevs))) + (define-abbrev-table table abbrevs))))) + +(defun read-abbrev-file (&optional file quietly) + "Read abbrev definitions from file written with `write-abbrev-file'. +Optional argument FILE is the name of the file to read; +it defaults to the value of `abbrev-file-name'. +Optional second argument QUIETLY non-nil means don't print anything." + (interactive "fRead abbrev file: ") + (load (if (and file (> (length file) 0)) file abbrev-file-name) + nil quietly) + (setq save-abbrevs t abbrevs-changed nil)) + +(defun quietly-read-abbrev-file (&optional file) + "Read abbrev definitions from file written with write-abbrev-file. +Optional argument FILE is the name of the file to read; +it defaults to the value of `abbrev-file-name'. +Does not print anything." + ;(interactive "fRead abbrev file: ") + (read-abbrev-file file t)) + +(defun write-abbrev-file (file) + "Write all abbrev definitions to a file of Lisp code. +The file written can be loaded in another session to define the same abbrevs. +The argument FILE is the file name to write." + (interactive + (list + (read-file-name "Write abbrev file: " + (file-name-directory (expand-file-name abbrev-file-name)) + abbrev-file-name))) + (or (and file (> (length file) 0)) + (setq file abbrev-file-name)) + (save-excursion + (set-buffer (get-buffer-create " write-abbrev-file")) + (erase-buffer) + (let ((tables abbrev-table-name-list)) + (while tables + (insert-abbrev-table-description (car tables) nil) + (setq tables (cdr tables)))) + (write-region 1 (point-max) file) + (erase-buffer))) + +(defun add-mode-abbrev (arg) + "Define mode-specific abbrev for last word(s) before point. +Argument is how many words before point form the expansion; +or zero means the region is the expansion. +A negative argument means to undefine the specified abbrev. +Reads the abbreviation in the minibuffer. + +Don't use this function in a Lisp program; use `define-abbrev' instead." + ;; XEmacs change: + (interactive "P") + (add-abbrev + (if only-global-abbrevs + global-abbrev-table + (or local-abbrev-table + (error "No per-mode abbrev table"))) + "Mode" arg)) + +(defun add-global-abbrev (arg) + "Define global (all modes) abbrev for last word(s) before point. +The prefix argument specifies the number of words before point that form the +expansion; or zero means the region is the expansion. +A negative argument means to undefine the specified abbrev. +This command uses the minibuffer to read the abbreviation. + +Don't use this function in a Lisp program; use `define-abbrev' instead." + ;; XEmacs change: + (interactive "P") + (add-abbrev global-abbrev-table "Global" arg)) + +(defun add-abbrev (table type arg) + ;; XEmacs change: + (if (and (not arg) (region-active-p)) (setq arg 0) + (setq arg (prefix-numeric-value arg))) + (let ((exp (and (>= arg 0) + (buffer-substring + (point) + (if (= arg 0) (mark) + (save-excursion (forward-word (- arg)) (point)))))) + name) + (setq name + (read-string (format (if exp "%s abbrev for \"%s\": " + "Undefine %s abbrev: ") + type exp))) + (set-text-properties 0 (length name) nil name) + (if (or (null exp) + (not (abbrev-expansion name table)) + (y-or-n-p (format "%s expands to \"%s\"; redefine? " + name (abbrev-expansion name table)))) + (define-abbrev table (downcase name) exp)))) + +(defun inverse-add-mode-abbrev (arg) + "Define last word before point as a mode-specific abbrev. +With prefix argument N, defines the Nth word before point. +This command uses the minibuffer to read the expansion. +Expands the abbreviation after defining it." + (interactive "p") + (inverse-add-abbrev + (if only-global-abbrevs + global-abbrev-table + (or local-abbrev-table + (error "No per-mode abbrev table"))) + "Mode" arg)) + +(defun inverse-add-global-abbrev (arg) + "Define last word before point as a global (mode-independent) abbrev. +With prefix argument N, defines the Nth word before point. +This command uses the minibuffer to read the expansion. +Expands the abbreviation after defining it." + (interactive "p") + (inverse-add-abbrev global-abbrev-table "Global" arg)) + +(defun inverse-add-abbrev (table type arg) + (let (name nameloc exp) + (save-excursion + (forward-word (- arg)) + (setq name (buffer-substring (point) (progn (forward-word 1) + (setq nameloc (point)))))) + (set-text-properties 0 (length name) nil name) + (setq exp (read-string (format "%s expansion for \"%s\": " + type name))) + (if (or (not (abbrev-expansion name table)) + (y-or-n-p (format "%s expands to \"%s\"; redefine? " + name (abbrev-expansion name table)))) + (progn + (define-abbrev table (downcase name) exp) + (save-excursion + (goto-char nameloc) + (expand-abbrev)))))) + +(defun abbrev-prefix-mark (&optional arg) + "Mark current point as the beginning of an abbrev. +Abbrev to be expanded starts here rather than at beginning of word. +This way, you can expand an abbrev with a prefix: insert the prefix, +use this command, then insert the abbrev." + (interactive "P") + (or arg (expand-abbrev)) + (setq abbrev-start-location (point-marker) + abbrev-start-location-buffer (current-buffer)) + (let ((e (make-extent (point) (point)))) + (set-extent-begin-glyph e (make-glyph [string :data "-"])))) + +(defun expand-region-abbrevs (start end &optional noquery) + "For abbrev occurrence in the region, offer to expand it. +The user is asked to type y or n for each occurrence. +A prefix argument means don't query; expand all abbrevs. +If called from a Lisp program, arguments are START END &optional NOQUERY." + (interactive "r\nP") + (save-excursion + (goto-char start) + (let ((lim (- (point-max) end)) + pnt string) + (while (and (not (eobp)) + (progn (forward-word 1) + (<= (setq pnt (point)) (- (point-max) lim)))) + (if (abbrev-expansion + (setq string + (buffer-substring + (save-excursion (forward-word -1) (point)) + pnt))) + (if (or noquery (y-or-n-p (format "Expand `%s'? " string))) + (expand-abbrev))))))) + +;;; abbrev.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/ChangeLog --- a/lisp/apel/ChangeLog Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -1997-07-14 MORIOKA Tomohiko - - * emu: Version 7.44 was released. - * APEL: Version 3.4 was released. - -1997-07-13 MORIOKA Tomohiko - - * std11-parse.el (std11-parse-ascii-token): Allow non-ASCII - characters in comments. - -1997-06-28 MORIOKA Tomohiko - - * file-detect.el: Add autoload comments for function `add-path', - `add-latest-path', `get-latest-path', `file-installed-p', - `exec-installed-p', `module-installed-p' and variable - `exec-suffix-list'. - -Sat May 10 19:39:12 1997 MORIOKA Tomohiko - - * README.en (What's APEL?): Add std11 and mule-caesar.el. - - -1997-05-09 MORIOKA Tomohiko - - * emu: Version 7.43.1 was released. - * APEL: Version 3.3.2 was released. - -Fri May 9 01:23:44 1997 MORIOKA Tomohiko - - * APEL-ELS: Add mule-caesar.el. - - * mule-caesar.el: New file. - - -1997-04-30 MORIOKA Tomohiko - - * emu: Version 7.43 was released. - * APEL: Version 3.3.1 was released. - -Wed Apr 30 12:40:32 1997 MORIOKA Tomohiko - - * Makefile: add `release'. - -Mon Apr 28 16:47:30 1997 MORIOKA Tomohiko - - * Makefile: `TARFILE' was abolished. - -Thu Apr 3 17:14:39 1997 MORIOKA Tomohiko - - * APEL-ELS: std11.el and std11-parse.el were moved from mu/. - - -1997-03-20 MORIOKA Tomohiko - - * APEL: Version 3.3 was released. - - * APEL-CFG (EMU_PREFIX, EMU_DIR): New variables. - * APEL-MK: install emu. - -Thu Mar 20 06:09:03 1997 MORIOKA Tomohiko - - * Makefile: Add README.en. - -Thu Mar 20 06:08:29 1997 MORIOKA Tomohiko - - * file-detect.el: Header and DOC-strings were modified. - -Thu Mar 20 06:03:51 1997 MORIOKA Tomohiko - - * README.en: New file. - -Thu Mar 20 05:48:02 1997 MORIOKA Tomohiko - - * filename.el: Add DOC-strings. - - * APEL-MK (install-apel): Use `compile-apel'. - - * Makefile (install): Don't depend on `elc'. - -Thu Mar 20 02:04:19 1997 MORIOKA Tomohiko - - * APEL-MK: Setting for load-path and requiring install were moved - from APEL-CFG. - - (install-apel): Compile apel-modules. - - * APEL-CFG: Setting for load-path and requiring install were moved - to APEL-MK. - - -1997-03-14 MORIOKA Tomohiko - - * APEL: Version 3.2 was released. - -Fri Mar 14 09:54:04 1997 MORIOKA Tomohiko - - * file-detect.el (get-latest-path): Check directory is exist or not. - -Fri Mar 14 09:25:15 1997 MORIOKA Tomohiko - - * APEL-ELS: Add install.el. - -Fri Mar 14 07:24:37 1997 MORIOKA Tomohiko - - * Makefile, APEL-MK, APEL-CFG: New file. - -1997-03-10 MORIOKA Tomohiko - - * atype.el (field-unify): fixed. - -1997-03-10 MORIOKA Tomohiko - - * filename.el (filename-filters): Use `exec-installed-p' instead - of `file-installed-p' to search "kakasi". - -1997-03-10 MORIOKA Tomohiko - - * file-detect.el (module-installed-p): Use function - `exec-installed-p'. - - * file-detect.el (exec-suffix-list): New variable. - (exec-installed-p): New function. - -1997-03-04 MORIOKA Tomohiko - - * APEL-ELS (apel-modules): Add filename.el. - - * APEL-ELS: Initial revision - -1997-03-04 MORIOKA Tomohiko - - * filename.el (filename-replacement-alist): Don't use function - `string-to-char-list' and `expand-char-ranges'; Don't require - tl-str. - (filename-special-filter): Use function `assoc-if' instead of - `ASSOC'; Require cl instead of tl-list. - (poly-funcall): New inline-function; copied from tl-list.el. - -1997-03-03 MORIOKA Tomohiko - - * atype.el: Alias `fetch-field', `fetch-field-value', `put-field' - and `delete-field' were abolished. - - Don't require tl-str and tl-list. - - Require alist. - - (field-unify): Don't use function `symbol-concat'. - (assoc-unify): Use function `assoc' directly; use function - `put-alist' directly; use function `del-alist' directly. - - * atype.el: Function `put-fields' was abolished. - - * atype.el: tl-atype.el was renamed to atype.el. - -1997-03-03 MORIOKA Tomohiko - - * atype.el: tl-atype.el was renamed to atype.el. - -1997-03-03 MORIOKA Tomohiko - - * file-detect.el (file-installed-p): Fixed DOC-string. - -1997-02-28 Tomohiko Morioka - - * alist.el: New module; separated from tl-list.el. diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/ChangeLog.emu --- a/lisp/apel/ChangeLog.emu Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,352 +0,0 @@ -1997-08-25 MORIOKA Tomohiko - - * emu-x20.el (mime-charset-coding-system-alist): iso-2022-jp-2 is - defined as coding-system. - - -1997-07-14 MORIOKA Tomohiko - - * emu: Version 7.44 was released. - -1997-07-13 MORIOKA Tomohiko - - * emu-e20.el (mime-charset-coding-system-alist): `iso-2022-ss2-7' - -> `iso-2022-7bit-ss2'. (for Emacs 20.0.90) - -1997-06-28 MORIOKA Tomohiko - - * richtext.el: Add autoload comments for `richtext-encode' and - `richtext-decode'. - - * emu.el: Check richtext.el is bundled. - -1997-06-08 MORIOKA Tomohiko - - * emu-x20.el (mime-charset-coding-system-alist): iso-8859-1, - hz-gb-2312, cn-gb-2312, gb2312, cn-big5 and koi8-r were defined as - coding-system. - - * emu-x20.el: Don't require cyrillic. - -Thu May 22 04:46:57 1997 MORIOKA Tomohiko - - * emu-mule.el (make-char): New alias. - - * emu-e20.el: Alias `make-character' was abolished. - - -1997-05-09 MORIOKA Tomohiko - - * emu: Version 7.43.1 was released. - -Thu May 8 22:21:36 1997 MORIOKA Tomohiko - - * emu-x20.el: Use `binary' instead of `no-conversion' temporary. - - -1997-04-30 MORIOKA Tomohiko - - * emu: Version 7.43 was released. - - * emu-x20.el: several changes for XEmacs 20.1-b12. - -Tue Apr 8 09:47:40 1997 MORIOKA Tomohiko - - * emu.el (point-at-eol): New function. - -Sat Apr 5 16:23:23 1997 MORIOKA Tomohiko - - * emu-nemacs.el: `tl:available-face-attribute-alist' -> - `emu:available-face-attribute-alist'. - - * emu-nemacs.el, emu-mule.el: `tl:make-overlay' -> `make-overlay'; - `tl:overlay-put' -> `overlay-put'. - -Sat Apr 5 06:50:48 1997 MORIOKA Tomohiko - - * emu-xemacs.el: Alias `tl:make-overlay', `tl:overlay-put' and - `tl:overlay-buffer' were abolished; Function `tl:move-overlay' - were abolished. - - * emu-19.el: Alias `tl:make-overlay', `tl:overlay-put' and - `tl:overlay-buffer' were abolished. - - * emu-18.el: `tl:overlay-buffer' -> `overlay-buffer'. - - * emu-xemacs.el: Require overlay. - - * emu.el (char-or-char-int-p): New XEmacs 20 emulating alias. - - * emu.el (minibuffer-prompt-width): New function for Emacs 18 and - XEmacs. - - -1997-03-14 MORIOKA Tomohiko - - * emu: Version 7.40.1 was released. - -Fri Mar 14 07:19:59 1997 MORIOKA Tomohiko - - * Makefile, EMU-MK: New file. - - * EMU-ELS: rearrangement. - - * EMU-CFG: New file - -Wed Mar 12 14:18:27 1997 MORIOKA Tomohiko - - * emu-x20.el: Modified for changing XEmacs/mule API about - `file-coding-system' -> `buffer-file-coding-system'. - - -1997-03-10 MORIOKA Tomohiko - - * emu: Version 7.40 was released. - - * emu-x20.el (as-binary-process, as-binary-output-file): Use - `coding-system-for-write' instead of `file-coding-system'. - - (as-binary-input-file, insert-binary-file-contents-literally): Use - `coding-system-for-read' instead of `file-coding-system-for-read'. - - * emu-e20.el (mime-charset-coding-system-alist): Delete - `iso-2022-int-1' and `shift_jis'. - -1997-03-06 MORIOKA Tomohiko - - * emu.el (defmacro-maybe): New macro. - (save-selected-window): Use `defmacro-maybe'. - - * emu-18.el (defsubst): New macro. - -1997-03-06 MORIOKA Tomohiko - - * emu-x20.el: Constant `*ctext*', `*hz*', `*big5', `*euc-kr*' and - `*koi8*' were abolished. - -1997-03-06 MORIOKA Tomohiko - - * emu-19.el: Alias `tl:add-text-properties' was abolished. - - * emu-18.el, emu-xemacs.el: Function `tl:add-text-properties' was - abolished. - -1997-03-06 MORIOKA Tomohiko - - * emu.el (buffer-substring-no-properties): Use - `set-text-properties' instead of `tl:set-text-properties'. - - * emu-19.el: Alias `tl:set-text-properties' was abolished. - - * emu-18.el, emu-xemacs.el: Function `tl:set-text-properties' was - abolished. - -1997-03-04 MORIOKA Tomohiko - - * emu-19.el (find-face): New function. - - -1997-03-03 MORIOKA Tomohiko - - * emu: Version 7.38.1 was released. - -1997-03-03 Oscar Figueiredo - - * emu-xemacs.el (tl:add-text-properties): In tm-ew-d.el, the - function mime/decode-encoded-word calls tl:add-text-properties - with 4 parameters while it is defined in emu-xemacs.el to take 3 - parameters only. (cf. [bug-tm-en:1246]) - - -1997-02-13 MORIOKA Tomohiko - - * emu: Version 7.38 was released. - - * emu.el: Function `insert-binary-file-contents-literally' was - moved to emu-{nemacs|e19|mule|x20|e20}.el. - - * emu-x20.el, emu-e20.el, emu-mule.el, emu-e19.el, emu-nemacs.el - (insert-binary-file-contents-literally): New function; moved from - emu.el. - - -1997-02-12 MORIOKA Tomohiko - - * emu: Version 7.37.7 was released. - -1997-02-12 MORIOKA Tomohiko - - * emu-x20.el: Variable `xemacs-beta-version' was abolished. - -1997-02-12 MORIOKA Tomohiko - - * emu-x20.el (as-binary-process): Variable `file-coding-system' is - effective for `call-process-region'. - - -1997-01-31 MORIOKA Tomohiko - - * emu: Version 7.37.6 was released. - -Thu Jan 30 16:55:00 1997 MORIOKA Tomohiko - - * richtext.el (richtext-decode): Variable - `enriched-fill-after-visiting' is not found in enriched.el bundled - in Emacs 19.34.91-delta. - - -1997-01-30 MORIOKA Tomohiko - - * emu: Version 7.37.5 was released. - -Wed Jan 29 15:48:26 1997 MORIOKA Tomohiko - - * emu-x20.el, emu-e20.el, emu-e19.el, emu-mule.el, emu-nemacs.el - (as-binary-output-file): New macro. - -Mon Jan 27 12:11:32 1997 MORIOKA Tomohiko - - * emu-e20.el (mime-charset-coding-system-alist): Modified for GNU - MULE 19.34.91-delta. - (mime-charset-to-coding-system): Modified for GNU MULE - 19.34.91-delta. - - -1997-01-21 MORIOKA Tomohiko - - * emu: Version 7.37.4 was released. - -Sat Jan 18 09:44:43 1997 MORIOKA Tomohiko - - * emu-x20.el (charsets-mime-charset-alist): Sync with emu-e20.el - 7.9. - (default-mime-charset): Default was changed to `x-ctext'. - (mime-charset-coding-system-alist): Add `x-ctext', `hz-gb-2312', - `cn-gb-2312' and `cn-big5'; `x-iso-2022-jp-2' and `x-shiftjis' was - abolished. - -Sat Jan 18 09:35:35 1997 MORIOKA Tomohiko - - * emu-e20.el: Function `regulate-latin-char' and - `regulate-latin-string' were abolished. - - * emu-e20.el (sset): Function `string-embed-string' was renamed to - `store-substring'. - -Wed Jan 15 18:01:13 1997 MORIOKA Tomohiko - - * emu-e20.el (fontset-pixel-size): modified for GNU MULE 19.34.91. - -Wed Jan 15 16:42:47 1997 MORIOKA Tomohiko - - * emu-e20.el: Alias `charset-columns' was abolished. - Function `charset-iso-class' was abolished. - - * emu-e20.el: for GNU MULE 19.34.91. - -Tue Jan 14 06:35:53 1997 MORIOKA Tomohiko - - * emu-x20.el: Alias `charset-description', `find-charset-string', - `find-charset-region', `char-width', `string-width' and `sref' has - been defined in XEmacs/mule. - - Function `find-non-ascii-charset-string', - `find-non-ascii-charset-region', `char-bytes', `char-length', - `char-columns', `string-columns' and `truncate-string' has been - defined in XEmacs/mule. - - -Mon Dec 23 14:56:40 1996 MORIOKA Tomohiko - - * emu: Version 7.37.3 was released. - -Wed Dec 18 13:12:15 1996 MORIOKA Tomohiko - - * emu-e20.el (as-binary-process): Fixed. - - -Mon Dec 16 14:57:02 1996 MORIOKA Tomohiko - - * emu: Version 7.37.2 was released. - -Thu Dec 12 02:29:18 1996 MORIOKA Tomohiko - - * emu-e20.el: Header was modified. - - -Tue Dec 10 14:41:46 1996 MORIOKA Tomohiko - - * emu: Version 7.37.1 was released. - - * emu-e19.el: `charset-latin-1' -> `charset-latin-iso8859-1'. - - * emu-e19.el: Constants to emulate MULE 2.3 leading-char were - abolished. - (find-charset-string, find-charset-region): Use constant - `charset-latin-1' instead of `lc-ltn1'. - -Sat Dec 7 06:07:15 1996 MORIOKA Tomohiko - - * emu-x20.el: Constants to emulate MULE 2.3 leading-char were - abolished. - - * emu-x20.el: Sync with patch about charset naming rule - (cf. [xemacs-beta:91]) - -Thu Dec 5 15:15:39 1996 MORIOKA Tomohiko - - * emu-x20.el: Sync with XEmacs 20.0 b30. - - -Wed Dec 4 04:55:36 1996 MORIOKA Tomohiko - - * emu: Version 7.37 was released. - -Fri Nov 29 21:22:25 1996 Shuhei KOBAYASHI - - * emu.el (match-string): New function for Emacs 19.28 or earlier. - -Thu Nov 28 19:25:12 1996 MORIOKA Tomohiko - - * richtext.el (richtext-decode): Unused local variable `nc' was - abolished. - - * richtext.el (richtext-decode): Unused local variable `pc' was - abolished. - -Thu Nov 28 19:16:18 1996 MORIOKA Tomohiko - - * emu.el (defun-maybe): New macro. - (buffer-substring-no-properties, add-to-list, buffer-live-p, - functionp): Use macro `defun-maybe' instead of `sysdep-defun'. - - * emu-xemacs.el: Don't use sysdep.el. - - * emu-18.el, emu-19.el: Function `sysdep-defun' was abolished. - -Thu Nov 28 18:02:42 1996 MORIOKA Tomohiko - - * emu.el (buffer-substring-no-properties, add-to-list, - buffer-live-p, functionp): Use `sysdep-defun'. - -Thu Nov 28 17:59:45 1996 MORIOKA Tomohiko - - * emu-xemacs.el: Use sysdep.el. - - * emu-19.el, emu-18.el (sysdep-defun): New macro. - -Wed Nov 27 13:40:42 1996 MORIOKA Tomohiko - - * emu-e20.el (fontset-pixel-size): Renamed from - `fontset-pixel-height'. - - -Sat Nov 16 08:37:04 1996 MORIOKA Tomohiko - - * emu: Version 7.34 was released. - -Fri Nov 15 13:59:53 1996 MORIOKA Tomohiko - - * emu-xemacs.el: Redefine `file-relative-name' if it is broken. - - * EMU-ELS: New file. diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/alist.el --- a/lisp/apel/alist.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -;;; alist.el --- utility functions about assoc-list - -;; Copyright (C) 1993,1994,1995,1996 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Version: -;; $Id: alist.el,v 1.1 1997/06/03 04:18:34 steve Exp $ -;; Keywords: alist - -;; This file is part of SEMI (SEMI is Emacs MIME Interfaces). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(defun put-alist (item value alist) - "Modify ALIST to set VALUE to ITEM. -If there is a pair whose car is ITEM, replace its cdr by VALUE. -If there is not such pair, create new pair (ITEM . VALUE) and -return new alist whose car is the new pair and cdr is ALIST. -\[tomo's ELIS like function]" - (let ((pair (assoc item alist))) - (if pair - (progn - (setcdr pair value) - alist) - (cons (cons item value) alist) - ))) - -(defun del-alist (item alist) - "If there is a pair whose key is ITEM, delete it from ALIST. -\[tomo's ELIS emulating function]" - (if (equal item (car (car alist))) - (cdr alist) - (let ((pr alist) - (r (cdr alist)) - ) - (catch 'tag - (while (not (null r)) - (if (equal item (car (car r))) - (progn - (rplacd pr (cdr r)) - (throw 'tag alist))) - (setq pr r) - (setq r (cdr r)) - ) - alist)))) - -(defun set-alist (symbol item value) - "Modify a alist indicated by SYMBOL to set VALUE to ITEM." - (or (boundp symbol) - (set symbol nil) - ) - (set symbol (put-alist item value (symbol-value symbol))) - ) - -(defun remove-alist (symbol item) - "Remove ITEM from the alist indicated by SYMBOL." - (and (boundp symbol) - (set symbol (del-alist item (symbol-value symbol))) - )) - -(defun modify-alist (modifier default) - "Modify alist DEFAULT into alist MODIFIER." - (mapcar (function - (lambda (as) - (setq default (put-alist (car as)(cdr as) default)) - )) - modifier) - default) - -(defun set-modified-alist (sym modifier) - "Modify a value of a symbol SYM into alist MODIFIER. -The symbol SYM should be alist. If it is not bound, -its value regard as nil." - (if (not (boundp sym)) - (set sym nil) - ) - (set sym (modify-alist modifier (eval sym))) - ) - - -;;; @ end -;;; - -(provide 'alist) - -;;; alist.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/atype.el --- a/lisp/apel/atype.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -;;; atype.el --- atype functions - -;; Copyright (C) 1994,1995,1996,1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Version: $Id: atype.el,v 1.1 1997/06/03 04:18:34 steve Exp $ -;; Keywords: atype - -;; This file is part of APEL (A Portable Emacs Library). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(require 'emu) -(require 'alist) - - -;;; @ field unifier -;;; - -(defun field-unifier-for-default (a b) - (let ((ret - (cond ((equal a b) a) - ((null (cdr b)) a) - ((null (cdr a)) b) - ))) - (if ret - (list nil ret nil) - ))) - -(defun field-unify (a b) - (let ((f - (let ((type (car a))) - (and (symbolp type) - (intern (concat "field-unifier-for-" (symbol-name type))) - )))) - (or (fboundp f) - (setq f (function field-unifier-for-default)) - ) - (funcall f a b) - )) - - -;;; @ type unifier -;;; - -(defun assoc-unify (class instance) - (catch 'tag - (let ((cla (copy-alist class)) - (ins (copy-alist instance)) - (r class) - cell aret ret prev rest) - (while r - (setq cell (car r)) - (setq aret (assoc (car cell) ins)) - (if aret - (if (setq ret (field-unify cell aret)) - (progn - (if (car ret) - (setq prev (put-alist (car (car ret)) - (cdr (car ret)) - prev)) - ) - (if (nth 2 ret) - (setq rest (put-alist (car (nth 2 ret)) - (cdr (nth 2 ret)) - rest)) - ) - (setq cla (put-alist (car cell)(cdr (nth 1 ret)) cla)) - (setq ins (del-alist (car cell) ins)) - ) - (throw 'tag nil) - )) - (setq r (cdr r)) - ) - (setq r (copy-alist ins)) - (while r - (setq cell (car r)) - (setq aret (assoc (car cell) cla)) - (if aret - (if (setq ret (field-unify cell aret)) - (progn - (if (car ret) - (setq prev (put-alist (car (car ret)) - (cdr (car ret)) - prev)) - ) - (if (nth 2 ret) - (setq rest (put-alist (car (nth 2 ret)) - (cdr (nth 2 ret)) - rest)) - ) - (setq cla (del-alist (car cell) cla)) - (setq ins (put-alist (car cell)(cdr (nth 1 ret)) ins)) - ) - (throw 'tag nil) - )) - (setq r (cdr r)) - ) - (list prev (append cla ins) rest) - ))) - -(defun get-unified-alist (db al) - (let ((r db) ret) - (catch 'tag - (while r - (if (setq ret (nth 1 (assoc-unify (car r) al))) - (throw 'tag ret) - ) - (setq r (cdr r)) - )))) - - -;;; @ utilities -;;; - -(defun delete-atype (atl al) - (let* ((r atl) ret oal) - (setq oal - (catch 'tag - (while r - (if (setq ret (nth 1 (assoc-unify (car r) al))) - (throw 'tag (car r)) - ) - (setq r (cdr r)) - ))) - (delete oal atl) - )) - -(defun remove-atype (sym al) - (and (boundp sym) - (set sym (delete-atype (eval sym) al)) - )) - -(defun replace-atype (atl old-al new-al) - (let* ((r atl) ret oal) - (if (catch 'tag - (while r - (if (setq ret (nth 1 (assoc-unify (car r) old-al))) - (throw 'tag (rplaca r new-al)) - ) - (setq r (cdr r)) - )) - atl))) - -(defun set-atype (sym al &rest options) - (if (null (boundp sym)) - (set sym al) - (let* ((replacement (memq 'replacement options)) - (ignore-fields (car (cdr (memq 'ignore options)))) - (remove (or (car (cdr (memq 'remove options))) - (let ((ral (copy-alist al))) - (mapcar (function - (lambda (type) - (setq ral (del-alist type ral)) - )) - ignore-fields) - ral))) - ) - (set sym - (or (if replacement - (replace-atype (eval sym) remove al) - ) - (cons al - (delete-atype (eval sym) remove) - ) - ))))) - - -;;; @ end -;;; - -(provide 'atype) - -;;; atype.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/auto-autoloads.el --- a/lisp/apel/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'apel-autoloads) (error "Already loaded")) - -;;;### (autoloads (module-installed-p exec-installed-p file-installed-p get-latest-path add-latest-path add-path) "file-detect" "apel/file-detect.el") - -(autoload 'add-path "file-detect" "\ -Add PATH to `load-path' if it exists under `default-load-path' -directories and it does not exist in `load-path'. - -You can use following PATH styles: - load-path relative: \"PATH/\" - (it is searched from `defaul-load-path') - home directory relative: \"~/PATH/\" \"~USER/PATH/\" - absolute path: \"/HOO/BAR/BAZ/\" - -You can specify following OPTIONS: - 'all-paths search from `load-path' - instead of `default-load-path' - 'append add PATH to the last of `load-path'" nil nil) - -(autoload 'add-latest-path "file-detect" "\ -Add latest path matched by PATTERN to `load-path' -if it exists under `default-load-path' directories -and it does not exist in `load-path'. - -If optional argument ALL-PATHS is specified, it is searched from all -of load-path instead of default-load-path. [file-detect.el]" nil nil) - -(autoload 'get-latest-path "file-detect" "\ -Return latest directory in default-load-path -which is matched to regexp PATTERN. -If optional argument ALL-PATHS is specified, -it is searched from all of load-path instead of default-load-path." nil nil) - -(autoload 'file-installed-p "file-detect" "\ -Return absolute-path of FILE if FILE exists in PATHS. -If PATHS is omitted, `load-path' is used." nil nil) - -(defvar exec-suffix-list '("") "\ -*List of suffixes for executable.") - -(autoload 'exec-installed-p "file-detect" "\ -Return absolute-path of FILE if FILE exists in PATHS. -If PATHS is omitted, `exec-path' is used. -If suffixes is omitted, `exec-suffix-list' is used." nil nil) - -(autoload 'module-installed-p "file-detect" "\ -Return t if module is provided or exists in PATHS. -If PATHS is omitted, `load-path' is used." nil nil) - -;;;*** - -;;;### (autoloads (richtext-decode richtext-encode) "richtext" "apel/richtext.el") - -(autoload 'richtext-encode "richtext" nil nil nil) - -(autoload 'richtext-decode "richtext" nil nil nil) - -;;;*** - -(provide 'apel-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/emu-e19.el --- a/lisp/apel/emu-e19.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,285 +0,0 @@ -;;; emu-e19.el --- emu module for Emacs 19 and XEmacs 19 - -;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Version: $Id: emu-e19.el,v 1.1 1997/06/03 04:18:35 steve Exp $ -;; Keywords: emulation, compatibility, mule, Latin-1 - -;; This file is part of emu. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -;;; @ version and variant specific features -;;; - -(cond (running-xemacs - (require 'emu-xemacs)) - (running-emacs-19 - (require 'emu-19) - )) - - -;;; @ character set -;;; - -(defconst charset-ascii 0 "Character set of ASCII") -(defconst charset-latin-iso8859-1 129 "Character set of ISO-8859-1") - -(defun charset-description (charset) - "Return description of CHARSET. [emu-e19.el]" - (if (< charset 128) - (documentation-property 'charset-ascii 'variable-documentation) - (documentation-property 'charset-latin-iso8859-1 'variable-documentation) - )) - -(defun charset-registry (charset) - "Return registry name of CHARSET. [emu-e19.el]" - (if (< charset 128) - "ASCII" - "ISO8859-1")) - -(defun charset-columns (charset) - "Return number of columns a CHARSET occupies when displayed. -\[emu-e19.el]" - 1) - -(defun charset-direction (charset) - "Return the direction of a character of CHARSET by - 0 (left-to-right) or 1 (right-to-left). [emu-e19.el]" - 0) - -(defun find-charset-string (str) - "Return a list of charsets in the string. -\[emu-e19.el; Mule emulating function]" - (if (string-match "[\200-\377]" str) - (list charset-latin-iso8859-1) - )) - -(defalias 'find-non-ascii-charset-string 'find-charset-string) - -(defun find-charset-region (start end) - "Return a list of charsets in the region between START and END. -\[emu-e19.el; Mule emulating function]" - (if (save-excursion - (save-restriction - (narrow-to-region start end) - (goto-char start) - (re-search-forward "[\200-\377]" nil t) - )) - (list charset-latin-iso8859-1) - )) - -(defalias 'find-non-ascii-charset-region 'find-charset-region) - - -;;; @ coding-system -;;; - -(defconst *internal* nil) -(defconst *ctext* nil) -(defconst *noconv* nil) - -(defun decode-coding-string (string coding-system) - "Decode the STRING which is encoded in CODING-SYSTEM. -\[emu-e19.el; Emacs 20 emulating function]" - string) - -(defun encode-coding-string (string coding-system) - "Encode the STRING as CODING-SYSTEM. -\[emu-e19.el; Emacs 20 emulating function]" - string) - -(defun decode-coding-region (start end coding-system) - "Decode the text between START and END which is encoded in CODING-SYSTEM. -\[emu-e19.el; Emacs 20 emulating function]" - 0) - -(defun encode-coding-region (start end coding-system) - "Encode the text between START and END to CODING-SYSTEM. -\[emu-e19.el; Emacs 20 emulating function]" - 0) - -(defun detect-coding-region (start end) - "Detect coding-system of the text in the region between START and END. -\[emu-e19.el; Emacs 20 emulating function]" - ) - -(defun set-buffer-file-coding-system (coding-system &optional force) - "Set buffer-file-coding-system of the current buffer to CODING-SYSTEM. -\[emu-e19.el; Emacs 20 emulating function]" - ) - -(defmacro as-binary-process (&rest body) - (` (let (selective-display) ; Disable ^M to nl translation. - (,@ body) - ))) - -(defmacro as-binary-input-file (&rest body) - (` (let ((emx-binary-mode t)) ; Stop CRLF to LF conversion in OS/2 - (,@ body) - ))) - -(defmacro as-binary-output-file (&rest body) - (` (let ((emx-binary-mode t)) ; Stop CRLF to LF conversion in OS/2 - (,@ body) - ))) - - -;;; @@ for old MULE emulation -;;; - -(defun code-convert-string (str ic oc) - "Convert code in STRING from SOURCE code to TARGET code, -On successful converion, returns the result string, -else returns nil. [emu-e19.el; old MULE emulating function]" - str) - -(defun code-convert-region (beg end ic oc) - "Convert code of the text between BEGIN and END from SOURCE -to TARGET. On successful conversion returns t, -else returns nil. [emu-e19.el; old MULE emulating function]" - t) - - -;;; @ binary access -;;; - -(defun insert-binary-file-contents-literally - (filename &optional visit beg end replace) - "Like `insert-file-contents-literally', q.v., but don't code conversion. -A buffer may be modified in several ways after reading into the buffer due -to advanced Emacs features, such as file-name-handlers, format decoding, -find-file-hooks, etc. - This function ensures that none of these modifications will take place." - (let ((emx-binary-mode t)) - (insert-file-contents-literally filename visit beg end replace) - )) - - -;;; @ MIME charset -;;; - -(defvar charsets-mime-charset-alist - (list (cons (list charset-ascii) 'us-ascii))) - -(defvar default-mime-charset 'iso-8859-1) - -(defun mime-charset-to-coding-system (charset) - (if (stringp charset) - (setq charset (intern (downcase charset))) - ) - (and (memq charset (list 'us-ascii default-mime-charset)) - charset) - ) - -(defun detect-mime-charset-region (start end) - "Return MIME charset for region between START and END. -\[emu-e19.el]" - (if (save-excursion - (save-restriction - (narrow-to-region start end) - (goto-char start) - (re-search-forward "[\200-\377]" nil t) - )) - default-mime-charset - 'us-ascii)) - -(defun encode-mime-charset-region (start end charset) - "Encode the text between START and END as MIME CHARSET. -\[emu-e19.el]" - ) - -(defun decode-mime-charset-region (start end charset) - "Decode the text between START and END as MIME CHARSET. -\[emu-e19.el]" - ) - -(defun encode-mime-charset-string (string charset) - "Encode the STRING as MIME CHARSET. [emu-e19.el]" - string) - -(defun decode-mime-charset-string (string charset) - "Decode the STRING as MIME CHARSET. [emu-e19.el]" - string) - - -;;; @ character -;;; - -(defun char-charset (chr) - "Return the character set of char CHR. -\[emu-e19.el; XEmacs 20 emulating function]" - (if (< chr 128) - charset-ascii - charset-latin-iso8859-1)) - -(defun char-bytes (char) - "Return number of bytes a character in CHAR occupies in a buffer. -\[emu-e19.el; MULE emulating function]" - 1) - -(defalias 'char-length 'char-bytes) - -(defun char-columns (character) - "Return number of columns a CHARACTER occupies when displayed. -\[emu-e19.el]" - 1) - -;;; @@ for old MULE emulation -;;; - -(defalias 'char-width 'char-columns) - -(defalias 'char-leading-char 'char-charset) - - -;;; @ string -;;; - -(defalias 'string-columns 'length) - -(defun string-to-char-list (str) - (mapcar (function identity) str) - ) - -(defalias 'string-to-int-list 'string-to-char-list) - -(defalias 'sref 'aref) - -(defun truncate-string (str width &optional start-column) - "Truncate STR to fit in WIDTH columns. -Optional non-nil arg START-COLUMN specifies the starting column. -\[emu-e19.el; MULE 2.3 emulating function]" - (or start-column - (setq start-column 0)) - (substring str start-column width) - ) - -;;; @@ for old MULE emulation -;;; - -(defalias 'string-width 'length) - - -;;; @ end -;;; - -(provide 'emu-e19) - -;;; emu-e19.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/emu-x20.el --- a/lisp/apel/emu-x20.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -;;; emu-x20.el --- emu API implementation for XEmacs 20 with mule - -;; Copyright (C) 1994,1995,1996,1997 MORIOKA Tomohiko - -;; Author: MORIOKA Tomohiko -;; Version: $Id: emu-x20.el,v 1.3 1997/09/03 02:55:28 steve Exp $ -;; Keywords: emulation, compatibility, Mule, XEmacs - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Commentary: - -;; This module requires XEmacs 20.3-b5 or later with mule. - -;;; Code: - -(require 'emu-xemacs) - - -;;; @ coding-system -;;; - -(defconst *noconv* 'binary) - -(defmacro as-binary-process (&rest body) - `(let (selective-display ; Disable ^M to nl translation. - (coding-system-for-read 'binary) - (coding-system-for-write 'binary)) - ,@body)) - -(defmacro as-binary-input-file (&rest body) - `(let ((coding-system-for-read 'binary)) - ,@body)) - -(defmacro as-binary-output-file (&rest body) - `(let ((coding-system-for-write 'binary)) - ,@body)) - - -;;; @ binary access -;;; - -(defun insert-binary-file-contents-literally - (filename &optional visit beg end replace) - "Like `insert-file-contents-literally', q.v., but don't code conversion. -A buffer may be modified in several ways after reading into the buffer due -to advanced Emacs features, such as file-name-handlers, format decoding, -find-file-hooks, etc. - This function ensures that none of these modifications will take place." - (let ((coding-system-for-read 'binary)) - (insert-file-contents-literally filename visit beg end replace) - )) - - -;;; @ MIME charset -;;; - -(defvar charsets-mime-charset-alist - '(((ascii) . us-ascii) - ((ascii latin-iso8859-1) . iso-8859-1) - ((ascii latin-iso8859-2) . iso-8859-2) - ((ascii latin-iso8859-3) . iso-8859-3) - ((ascii latin-iso8859-4) . iso-8859-4) -;;; ((ascii cyrillic-iso8859-5) . iso-8859-5) - ((ascii cyrillic-iso8859-5) . koi8-r) - ((ascii arabic-iso8859-6) . iso-8859-6) - ((ascii greek-iso8859-7) . iso-8859-7) - ((ascii hebrew-iso8859-8) . iso-8859-8) - ((ascii latin-iso8859-9) . iso-8859-9) - ((ascii latin-jisx0201 - japanese-jisx0208-1978 japanese-jisx0208) . iso-2022-jp) - ((ascii korean-ksc5601) . euc-kr) - ((ascii chinese-gb2312) . cn-gb-2312) - ((ascii chinese-big5-1 chinese-big5-2) . cn-big5) - ((ascii latin-iso8859-1 greek-iso8859-7 - latin-jisx0201 japanese-jisx0208-1978 - chinese-gb2312 japanese-jisx0208 - korean-ksc5601 japanese-jisx0212) . iso-2022-jp-2) - ((ascii latin-iso8859-1 greek-iso8859-7 - latin-jisx0201 japanese-jisx0208-1978 - chinese-gb2312 japanese-jisx0208 - korean-ksc5601 japanese-jisx0212 - chinese-cns11643-1 chinese-cns11643-2) . iso-2022-int-1) - ((ascii latin-iso8859-1 latin-iso8859-2 - cyrillic-iso8859-5 greek-iso8859-7 - latin-jisx0201 japanese-jisx0208-1978 - chinese-gb2312 japanese-jisx0208 - korean-ksc5601 japanese-jisx0212 - chinese-cns11643-1 chinese-cns11643-2 - chinese-cns11643-3 chinese-cns11643-4 - chinese-cns11643-5 chinese-cns11643-6 - chinese-cns11643-7) . iso-2022-int-1) - )) - -(defvar default-mime-charset 'x-ctext) - -(defvar mime-charset-coding-system-alist - '((x-ctext . ctext)) - "Alist MIME CHARSET vs CODING-SYSTEM. -MIME CHARSET and CODING-SYSTEM must be symbol.") - -(defun mime-charset-to-coding-system (charset) - "Return coding-system by MIME charset." - (if (stringp charset) - (setq charset (intern (downcase charset))) - ) - (or (cdr (assq charset mime-charset-coding-system-alist)) - (and (memq charset (coding-system-list)) charset) - )) - -(defun detect-mime-charset-region (start end) - "Return MIME charset for region between START and END." - (charsets-to-mime-charset (charsets-in-region start end))) - -(defun encode-mime-charset-region (start end charset) - "Encode the text between START and END as MIME CHARSET." - (let ((cs (mime-charset-to-coding-system charset))) - (if cs - (encode-coding-region start end cs) - ))) - -(defun decode-mime-charset-region (start end charset) - "Decode the text between START and END as MIME CHARSET." - (let ((cs (mime-charset-to-coding-system charset))) - (if cs - (decode-coding-region start end cs) - ))) - -(defun encode-mime-charset-string (string charset) - "Encode the STRING as MIME CHARSET." - (let ((cs (mime-charset-to-coding-system charset))) - (if cs - (encode-coding-string string cs) - string))) - -(defun decode-mime-charset-string (string charset) - "Decode the STRING as MIME CHARSET." - (let ((cs (mime-charset-to-coding-system charset))) - (if cs - (decode-coding-string string cs) - string))) - - -;;; @ character -;;; - -;;; @@ Mule emulating aliases -;;; -;;; You should not use them. - -(defalias 'char-leading-char 'char-charset) - -(defun char-category (character) - "Return string of category mnemonics for CHAR in TABLE. -CHAR can be any multilingual character -TABLE defaults to the current buffer's category table." - (mapconcat (lambda (chr) - (char-to-string (int-char chr)) - ) - (char-category-list character) - "")) - - -;;; @ string -;;; - -(defun string-to-int-list (str) - (mapcar #'char-int str) - ) - - -;;; @ end -;;; - -(provide 'emu-x20) - -;;; emu-x20.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/emu-xemacs.el --- a/lisp/apel/emu-xemacs.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -;;; emu-xemacs.el --- emu API implementation for XEmacs - -;; Copyright (C) 1995 Free Software Foundation, Inc. -;; Copyright (C) 1995,1996,1997 MORIOKA Tomohiko - -;; Author: MORIOKA Tomohiko -;; Version: -;; $Id: emu-xemacs.el,v 1.1 1997/06/03 04:18:35 steve Exp $ -;; Keywords: emulation, compatibility, XEmacs - -;; This file is part of XEmacs. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Code: - -;;; @ face -;;; - -(or (fboundp 'face-list) - (defalias 'face-list 'list-faces) - ) - -(or (memq 'underline (face-list)) - (and (fboundp 'make-face) - (make-face 'underline) - )) - -(or (face-differs-from-default-p 'underline) - (set-face-underline-p 'underline t)) - - -;;; @ overlay -;;; - -(condition-case err - (require 'overlay) - (error (defalias 'make-overlay 'make-extent) - (defalias 'overlay-put 'set-extent-property) - (defalias 'overlay-buffer 'extent-buffer) - (defun move-overlay (extent start end &optional buffer) - (set-extent-endpoints extent start end) - ) - )) - - -;;; @ visible/invisible -;;; - -(defmacro enable-invisible ()) - -(defmacro end-of-invisible ()) - -(defun invisible-region (start end) - (if (save-excursion - (goto-char start) - (eq (following-char) ?\n) - ) - (setq start (1+ start)) - ) - (put-text-property start end 'invisible t) - ) - -(defun visible-region (start end) - (put-text-property start end 'invisible nil) - ) - -(defun invisible-p (pos) - (if (save-excursion - (goto-char pos) - (eq (following-char) ?\n) - ) - (setq pos (1+ pos)) - ) - (get-text-property pos 'invisible) - ) - -(defun next-visible-point (pos) - (save-excursion - (if (save-excursion - (goto-char pos) - (eq (following-char) ?\n) - ) - (setq pos (1+ pos)) - ) - (or (next-single-property-change pos 'invisible) - (point-max)) - )) - - -;;; @ mouse -;;; - -(defvar mouse-button-1 'button1) -(defvar mouse-button-2 'button2) -(defvar mouse-button-3 'button3) - - -;;; @ dired -;;; - -(or (fboundp 'dired-other-frame) - (defun dired-other-frame (dirname &optional switches) - "\"Edit\" directory DIRNAME. Like `dired' but makes a new frame." - (interactive (dired-read-dir-and-switches "in other frame ")) - (switch-to-buffer-other-frame (dired-noselect dirname switches)) - ) - ) - - -;;; @ string -;;; - -(defmacro char-list-to-string (char-list) - "Convert list of character CHAR-LIST to string. [emu-xemacs.el]" - `(mapconcat #'char-to-string ,char-list "")) - - -;;; @@ to avoid bug of XEmacs 19.14 -;;; - -(or (string-match "^../" - (file-relative-name "/usr/local/share" "/usr/local/lib")) - ;; This function was imported from Emacs 19.33. - (defun file-relative-name (filename &optional directory) - "Convert FILENAME to be relative to DIRECTORY -(default: default-directory). [emu-xemacs.el]" - (setq filename (expand-file-name filename) - directory (file-name-as-directory - (expand-file-name - (or directory default-directory)))) - (let ((ancestor "")) - (while (not (string-match (concat "^" (regexp-quote directory)) - filename)) - (setq directory (file-name-directory (substring directory 0 -1)) - ancestor (concat "../" ancestor))) - (concat ancestor (substring filename (match-end 0))) - )) - ) - - -;;; @ end -;;; - -(provide 'emu-xemacs) - -;;; emu-xemacs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/emu.el --- a/lisp/apel/emu.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -;;; emu.el --- Emulation module for each Emacs variants - -;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Version: $Id: emu.el,v 1.2 1997/06/29 23:12:06 steve Exp $ -;; Keywords: emulation, compatibility, NEmacs, MULE, Emacs/mule, XEmacs - -;; This file is part of emu. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(defmacro defun-maybe (name &rest everything-else) - (or (and (fboundp name) - (not (get name 'defun-maybe)) - ) - (` (or (fboundp (quote (, name))) - (progn - (defun (, name) (,@ everything-else)) - (put (quote (, name)) 'defun-maybe t) - )) - ))) - -(defmacro defmacro-maybe (name &rest everything-else) - (or (and (fboundp name) - (not (get name 'defmacro-maybe)) - ) - (` (or (fboundp (quote (, name))) - (progn - (defmacro (, name) (,@ everything-else)) - (put (quote (, name)) 'defmacro-maybe t) - )) - ))) - -(put 'defun-maybe 'lisp-indent-function 'defun) -(put 'defmacro-maybe 'lisp-indent-function 'defun) - - -(or (boundp 'emacs-major-version) - (defconst emacs-major-version (string-to-int emacs-version))) -(or (boundp 'emacs-minor-version) - (defconst emacs-minor-version - (string-to-int - (substring - emacs-version - (string-match (format "%d\\." emacs-major-version) emacs-version) - )))) - -(defvar running-emacs-18 (<= emacs-major-version 18)) -(defvar running-xemacs (string-match "XEmacs" emacs-version)) - -(defvar running-mule-merged-emacs (and (not (boundp 'MULE)) - (not running-xemacs) (featurep 'mule))) -(defvar running-xemacs-with-mule (and running-xemacs (featurep 'mule))) - -(defvar running-emacs-19 (and (not running-xemacs) (= emacs-major-version 19))) -(defvar running-emacs-19_29-or-later - (or (and running-emacs-19 (>= emacs-minor-version 29)) - (and (not running-xemacs)(>= emacs-major-version 20)))) - -(defvar running-xemacs-19 (and running-xemacs - (= emacs-major-version 19))) -(defvar running-xemacs-20-or-later (and running-xemacs - (>= emacs-major-version 20))) -(defvar running-xemacs-19_14-or-later - (or (and running-xemacs-19 (>= emacs-minor-version 14)) - running-xemacs-20-or-later)) - -(cond (running-mule-merged-emacs - ;; for mule merged EMACS - (require 'emu-e20) - ) - (running-xemacs-with-mule - ;; for XEmacs/mule - (require 'emu-x20) - ) - ((boundp 'MULE) - ;; for MULE 1.* and 2.* - (require 'emu-mule) - ) - ((boundp 'NEMACS) - ;; for NEmacs and NEpoch - (require 'emu-nemacs) - ) - (t - ;; for EMACS 19 and XEmacs 19 (without mule) - (require 'emu-e19) - )) - - -;;; @ MIME charset -;;; - -(defun charsets-to-mime-charset (charsets) - "Return MIME charset from list of charset CHARSETS. -This function refers variable `charsets-mime-charset-alist' -and `default-mime-charset'. [emu.el]" - (if charsets - (or (catch 'tag - (let ((rest charsets-mime-charset-alist) - cell csl) - (while (setq cell (car rest)) - (if (catch 'not-subset - (let ((set1 charsets) - (set2 (car cell)) - obj) - (while set1 - (setq obj (car set1)) - (or (memq obj set2) - (throw 'not-subset nil) - ) - (setq set1 (cdr set1)) - ) - t)) - (throw 'tag (cdr cell)) - ) - (setq rest (cdr rest)) - ))) - default-mime-charset))) - - -;;; @ Emacs 19 emulation -;;; - -(defun-maybe minibuffer-prompt-width () - "Return the display width of the minibuffer prompt." - (save-excursion - (set-buffer (window-buffer (minibuffer-window))) - (current-column) - )) - - -;;; @ Emacs 19.29 emulation -;;; - -(defvar path-separator ":" - "Character used to separate concatenated paths.") - -(defun-maybe buffer-substring-no-properties (start end) - "Return the characters of part of the buffer, without the text properties. -The two arguments START and END are character positions; -they can be in either order. [Emacs 19.29 emulating function]" - (let ((string (buffer-substring start end))) - (set-text-properties 0 (length string) nil string) - string)) - -(defun-maybe match-string (num &optional string) - "Return string of text matched by last search. -NUM specifies which parenthesized expression in the last regexp. - Value is nil if NUMth pair didn't match, or there were less than NUM pairs. -Zero means the entire text matched by the whole regexp or whole string. -STRING should be given if the last search was by `string-match' on STRING. -\[Emacs 19.29 emulating function]" - (if (match-beginning num) - (if string - (substring string (match-beginning num) (match-end num)) - (buffer-substring (match-beginning num) (match-end num))))) - -(or running-emacs-19_29-or-later - running-xemacs - ;; for Emacs 19.28 or earlier - (fboundp 'si:read-string) - (progn - (fset 'si:read-string (symbol-function 'read-string)) - - (defun read-string (prompt &optional initial-input history) - "Read a string from the minibuffer, prompting with string PROMPT. -If non-nil, second arg INITIAL-INPUT is a string to insert before reading. -The third arg HISTORY, is dummy for compatibility. [emu.el] -See `read-from-minibuffer' for details of HISTORY argument." - (si:read-string prompt initial-input) - ) - )) - - -;;; @ Emacs 19.30 emulation -;;; - -;; This function was imported Emacs 19.30. -(defun-maybe add-to-list (list-var element) - "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet. -If you want to use `add-to-list' on a variable that is not defined -until a certain package is loaded, you should put the call to `add-to-list' -into a hook function that will be run only after loading the package. -\[Emacs 19.30 emulating function]" - (or (member element (symbol-value list-var)) - (set list-var (cons element (symbol-value list-var))) - )) - -(cond ((fboundp 'insert-file-contents-literally) - ) - ((boundp 'file-name-handler-alist) - (defun insert-file-contents-literally - (filename &optional visit beg end replace) - "Like `insert-file-contents', q.v., but only reads in the file. -A buffer may be modified in several ways after reading into the buffer due -to advanced Emacs features, such as file-name-handlers, format decoding, -find-file-hooks, etc. - This function ensures that none of these modifications will take place. -\[Emacs 19.30 emulating function]" - (let (file-name-handler-alist) - (insert-file-contents filename visit beg end replace) - )) - ) - (t - (defalias 'insert-file-contents-literally 'insert-file-contents) - )) - - -;;; @ Emacs 19.31 emulation -;;; - -(defun-maybe buffer-live-p (object) - "Return non-nil if OBJECT is a buffer which has not been killed. -Value is nil if OBJECT is not a buffer or if it has been killed. -\[Emacs 19.31 emulating function]" - (and object - (get-buffer object) - (buffer-name (get-buffer object)) - )) - -;; This macro was imported Emacs 19.33. -(defmacro-maybe save-selected-window (&rest body) - "Execute BODY, then select the window that was selected before BODY. -\[Emacs 19.31 emulating function]" - (list 'let - '((save-selected-window-window (selected-window))) - (list 'unwind-protect - (cons 'progn body) - (list 'select-window 'save-selected-window-window)))) - - -;;; @ XEmacs emulation -;;; - -(defun-maybe functionp (obj) - "Returns t if OBJ is a function, nil otherwise. -\[XEmacs emulating function]" - (or (subrp obj) - (byte-code-function-p obj) - (and (symbolp obj)(fboundp obj)) - (and (consp obj)(eq (car obj) 'lambda)) - )) - -(defun-maybe point-at-eol (&optional arg buffer) - "Return the character position of the last character on the current line. -With argument N not nil or 1, move forward N - 1 lines first. -If scan reaches end of buffer, return that position. -This function does not move point. [XEmacs emulating function]" - (save-excursion - (if buffer - (set-buffer buffer) - ) - (if arg - (forward-line (1- arg)) - ) - (end-of-line) - (point) - )) - - -;;; @ for XEmacs 20 -;;; - -(or (fboundp 'char-int) - (fset 'char-int (symbol-function 'identity)) - ) -(or (fboundp 'int-char) - (fset 'int-char (symbol-function 'identity)) - ) -(or (fboundp 'char-or-char-int-p) - (fset 'char-or-char-int-p (symbol-function 'integerp)) - ) - - -;;; @ for text/richtext and text/enriched -;;; - -(cond ((fboundp 'richtext-decode) - ;; have richtext.el - ) - ((or running-emacs-19_29-or-later running-xemacs-19_14-or-later) - ;; have enriched.el - (autoload 'richtext-decode "richtext") - (or (assq 'text/richtext format-alist) - (setq format-alist - (cons - (cons 'text/richtext - '("Extended MIME text/richtext format." - "Content-[Tt]ype:[ \t]*text/richtext" - richtext-decode richtext-encode t enriched-mode)) - format-alist))) - ) - (t - ;; don't have enriched.el - (autoload 'richtext-decode "tinyrich") - (autoload 'enriched-decode "tinyrich") - )) - - -;;; @ end -;;; - -(provide 'emu) - -;;; emu.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/file-detect.el --- a/lisp/apel/file-detect.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,168 +0,0 @@ -;;; file-detect.el --- Emacs Lisp file detection utility - -;; Copyright (C) 1996,1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Version: -;; $Id: file-detect.el,v 1.2 1997/06/29 23:12:06 steve Exp $ -;; Keywords: install, module - -;; This file is part of APEL (A Portable Emacs Library). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(defvar default-load-path load-path) - -;;;###autoload -(defun add-path (path &rest options) - "Add PATH to `load-path' if it exists under `default-load-path' -directories and it does not exist in `load-path'. - -You can use following PATH styles: - load-path relative: \"PATH/\" - (it is searched from `defaul-load-path') - home directory relative: \"~/PATH/\" \"~USER/PATH/\" - absolute path: \"/HOO/BAR/BAZ/\" - -You can specify following OPTIONS: - 'all-paths search from `load-path' - instead of `default-load-path' - 'append add PATH to the last of `load-path'" - (let ((rest (if (memq 'all-paths options) - load-path - default-load-path)) - p) - (if (and (catch 'tag - (while rest - (setq p (expand-file-name path (car rest))) - (if (file-directory-p p) - (throw 'tag p) - ) - (setq rest (cdr rest)) - )) - (not (member p load-path)) - ) - (setq load-path - (if (memq 'append options) - (append load-path (list p)) - (cons p load-path) - )) - ))) - -;;;###autoload -(defun add-latest-path (pattern &optional all-paths) - "Add latest path matched by PATTERN to `load-path' -if it exists under `default-load-path' directories -and it does not exist in `load-path'. - -If optional argument ALL-PATHS is specified, it is searched from all -of load-path instead of default-load-path. [file-detect.el]" - (let ((path (get-latest-path pattern all-paths))) - (if path - (add-to-list 'load-path path) - ))) - -;;;###autoload -(defun get-latest-path (pattern &optional all-paths) - "Return latest directory in default-load-path -which is matched to regexp PATTERN. -If optional argument ALL-PATHS is specified, -it is searched from all of load-path instead of default-load-path." - (catch 'tag - (let ((paths (if all-paths - load-path - default-load-path)) - dir) - (while (setq dir (car paths)) - (if (and (file-exists-p dir) - (file-directory-p dir) - ) - (let ((files (sort (directory-files dir t pattern t) - (function file-newer-than-file-p))) - file) - (while (setq file (car files)) - (if (file-directory-p file) - (throw 'tag file) - ) - (setq files (cdr files)) - ))) - (setq paths (cdr paths)) - )))) - -;;;###autoload -(defun file-installed-p (file &optional paths) - "Return absolute-path of FILE if FILE exists in PATHS. -If PATHS is omitted, `load-path' is used." - (if (null paths) - (setq paths load-path) - ) - (catch 'tag - (let (path) - (while paths - (setq path (expand-file-name file (car paths))) - (if (file-exists-p path) - (throw 'tag path) - ) - (setq paths (cdr paths)) - )))) - -;;;###autoload -(defvar exec-suffix-list '("") - "*List of suffixes for executable.") - -;;;###autoload -(defun exec-installed-p (file &optional paths suffixes) - "Return absolute-path of FILE if FILE exists in PATHS. -If PATHS is omitted, `exec-path' is used. -If suffixes is omitted, `exec-suffix-list' is used." - (or paths - (setq paths exec-path) - ) - (or suffixes - (setq suffixes exec-suffix-list) - ) - (catch 'tag - (while paths - (let ((stem (expand-file-name file (car paths))) - (sufs suffixes) - ) - (while sufs - (let ((file (concat stem (car sufs)))) - (if (file-exists-p file) - (throw 'tag file) - )) - (setq sufs (cdr sufs)) - )) - (setq paths (cdr paths)) - ))) - -;;;###autoload -(defun module-installed-p (module &optional paths) - "Return t if module is provided or exists in PATHS. -If PATHS is omitted, `load-path' is used." - (or (featurep module) - (exec-installed-p (symbol-name module) load-path '(".elc" ".el")) - )) - - -;;; @ end -;;; - -(provide 'file-detect) - -;;; file-detect.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/filename.el --- a/lisp/apel/filename.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -;;; filename.el --- file name filter - -;; Copyright (C) 1996,1997 MORIOKA Tomohiko - -;; Author: MORIOKA Tomohiko -;; Version: $Id: filename.el,v 1.1 1997/06/03 04:18:35 steve Exp $ -;; Keywords: file name, string - -;; This file is part of APEL (A Portable Emacs Library). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(require 'emu) -(require 'cl) - -(defsubst poly-funcall (functions argument) - "Apply initial ARGUMENT to sequence of FUNCTIONS. -FUNCTIONS is list of functions. - -(poly-funcall '(f1 f2 .. fn) arg) is as same as -(fn .. (f2 (f1 arg)) ..). - -For example, (poly-funcall '(car number-to-string) '(100)) returns -\"100\"." - (while functions - (setq argument (funcall (car functions) argument) - functions (cdr functions)) - ) - argument) - - -;;; @ variables -;;; - -(defvar filename-limit-length 21 "Limit size of file-name.") - -(defvar filename-replacement-alist - '(((?\ ?\t) . "_") - ((?! ?\" ?# ?$ ?% ?& ?' ?\( ?\) ?* ?/ - ?: ?\; ?< ?> ?? ?\[ ?\\ ?\] ?` ?{ ?| ?}) . "_") - (filename-control-p . "") - ) - "Alist list of characters vs. string as replacement. -List of characters represents characters not allowed as file-name.") - -(defvar filename-filters - (let ((filters '(filename-special-filter - filename-eliminate-top-low-lines - filename-canonicalize-low-lines - filename-maybe-truncate-by-size - filename-eliminate-bottom-low-lines - ))) - (require 'file-detect) - (if (exec-installed-p "kakasi") - (cons 'filename-japanese-to-roman-string filters) - filters)) - "List of functions for file-name filter.") - - -;;; @ filters -;;; - -(defun filename-japanese-to-roman-string (str) - (save-excursion - (set-buffer (get-buffer-create " *temp kakasi*")) - (erase-buffer) - (insert str) - (call-process-region (point-min)(point-max) "kakasi" t t t - "-Ha" "-Ka" "-Ja" "-Ea" "-ka") - (buffer-string) - )) - -(defun filename-control-p (character) - (let ((code (char-int character))) - (or (< code 32)(= code 127)) - )) - -(defun filename-special-filter (string) - (let (dest - (i 0) - (len (length string)) - (b 0) - ) - (while (< i len) - (let* ((chr (sref string i)) - (ret (assoc-if (function - (lambda (key) - (if (functionp key) - (funcall key chr) - (memq chr key) - ))) - filename-replacement-alist)) - ) - (if ret - (setq dest (concat dest (substring string b i)(cdr ret)) - i (+ i (char-length chr)) - b i) - (setq i (+ i (char-length chr))) - ))) - (concat dest (substring string b)) - )) - -(defun filename-eliminate-top-low-lines (string) - (if (string-match "^_+" string) - (substring string (match-end 0)) - string)) - -(defun filename-canonicalize-low-lines (string) - (let (dest) - (while (string-match "__+" string) - (setq dest (concat dest (substring string 0 (1+ (match-beginning 0))))) - (setq string (substring string (match-end 0))) - ) - (concat dest string) - )) - -(defun filename-maybe-truncate-by-size (string) - (if (and (> (length string) filename-limit-length) - (string-match "_" string filename-limit-length) - ) - (substring string 0 (match-beginning 0)) - string)) - -(defun filename-eliminate-bottom-low-lines (string) - (if (string-match "_+$" string) - (substring string 0 (match-beginning 0)) - string)) - - -;;; @ interface -;;; - -(defun replace-as-filename (string) - "Return safety filename from STRING. -It refers variable `filename-filters' and default filters refers -`filename-limit-length', `filename-replacement-alist'." - (and string - (poly-funcall filename-filters string) - )) - - -;;; @ end -;;; - -(provide 'filename) - -;;; filename.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/install.el --- a/lisp/apel/install.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -;;; install.el --- Emacs Lisp package install utility - -;; Copyright (C) 1996 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Created: 1996/8/18 -;; Version: $Id: install.el,v 1.1 1997/06/03 04:18:35 steve Exp $ -;; Keywords: install - -;; This file is part of tl (Tiny Library). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to -;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(require 'emu) -(require 'file-detect) - -;;; @ compile Emacs Lisp files -;;; - -(defun compile-elisp-module (module &optional path every-time) - (setq module (expand-file-name (symbol-name module) path)) - (let ((el-file (concat module ".el")) - (elc-file (concat module ".elc")) - ) - (if (or every-time - (file-newer-than-file-p el-file elc-file)) - (byte-compile-file el-file) - ) - )) - -(defun compile-elisp-modules (modules &optional path every-time) - (mapcar (function - (lambda (module) - (compile-elisp-module module path every-time) - )) - modules)) - - -;;; @ install files -;;; - -(defvar install-overwritten-file-modes (+ (* 64 6)(* 8 4) 4)) - -(defun install-file (file src dest &optional move overwrite) - (let ((src-file (expand-file-name file src))) - (if (file-exists-p src-file) - (let ((full-path (expand-file-name file dest))) - (if (and (file-exists-p full-path) overwrite) - (delete-file full-path) - ) - (copy-file src-file full-path t t) - (if move - (catch 'tag - (while (and (file-exists-p src-file) - (file-writable-p src-file)) - (condition-case err - (progn - (delete-file src-file) - (throw 'tag nil) - ) - (error (princ (format "%s\n" (nth 1 err)))) - )))) - (princ (format "%s -> %s\n" file dest)) - )) - )) - -(defun install-files (files src dest &optional move overwrite) - (or (file-exists-p dest) - (make-directory dest t) - ) - (mapcar (function (lambda (file) - (install-file file src dest move overwrite) - )) - files)) - - -;;; @@ install Emacs Lisp files -;;; - -(defun install-elisp-module (module src dest) - (let (el-file elc-file) - (let ((name (symbol-name module))) - (setq el-file (concat name ".el")) - (setq elc-file (concat name ".elc")) - ) - (let ((src-file (expand-file-name el-file src))) - (if (file-exists-p src-file) - (let ((full-path (expand-file-name el-file dest))) - (if (file-exists-p full-path) - (delete-file full-path) - ) - (copy-file src-file full-path t t) - (princ (format "%s -> %s\n" el-file dest)) - )) - (setq src-file (expand-file-name elc-file src)) - (if (file-exists-p src-file) - (let ((full-path (expand-file-name elc-file dest))) - (if (file-exists-p full-path) - (delete-file full-path) - ) - (copy-file src-file full-path t t) - (catch 'tag - (while (file-exists-p src-file) - (condition-case err - (progn - (delete-file src-file) - (throw 'tag nil) - ) - (error (princ (format "%s\n" (nth 1 err)))) - ))) - (princ (format "%s -> %s\n" elc-file dest)) - )) - ))) - -(defun install-elisp-modules (modules src dest) - (or (file-exists-p dest) - (make-directory dest t) - ) - (mapcar (function (lambda (module) - (install-elisp-module module src dest) - )) - modules)) - - -;;; @ detect install path -;;; - -(defvar install-prefix - (if (or running-emacs-18 running-xemacs) - (expand-file-name "../../.." exec-directory) - (expand-file-name "../../../.." data-directory) - )) ; install to shared directory (maybe "/usr/local") - -(defvar install-elisp-prefix - (if (>= emacs-major-version 19) - "site-lisp" - "local.lisp")) - -(defun install-detect-elisp-directory (&optional prefix elisp-prefix - allow-version-specific) - (or prefix - (setq prefix install-prefix) - ) - (or elisp-prefix - (setq elisp-prefix install-elisp-prefix) - ) - (or - (catch 'tag - (let ((rest default-load-path) - dir) - (while (setq dir (car rest)) - (if (string-match - (concat "^" - (expand-file-name (concat ".*/" elisp-prefix) prefix) - "$") - dir) - (if (or allow-version-specific - (not (string-match (format "%d\\.%d" - emacs-major-version - emacs-minor-version) dir)) - ) - (throw 'tag dir) - )) - (setq rest (cdr rest)) - ))) - (expand-file-name (concat - (if running-emacs-19_29-or-later - "share/" - "lib/") - (cond ((boundp 'NEMACS) "nemacs/") - ((boundp 'MULE) "mule/") - (running-xemacs - (if (featurep 'mule) - "xmule/" - "xemacs/")) - (t "emacs/")) - elisp-prefix) prefix) - )) - -(defvar install-default-elisp-directory - (install-detect-elisp-directory)) - - -;;; @ end -;;; - -(provide 'install) - -;;; install.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/mule-caesar.el --- a/lisp/apel/mule-caesar.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -;;; mule-caesar.el --- ROT 13-47 Caesar rotation utility - -;; Copyright (C) 1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Version: $Id: mule-caesar.el,v 1.1 1997/06/03 04:18:36 steve Exp $ -;; Keywords: ROT 13-47, caesar, mail, news, text/x-rot13-47 - -;; This file is part of APEL (A Portable Emacs Library). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(defun char-to-octet-list (character) - "Return list of octets in code table of graphic character set." - (let* ((code (char-int character)) - (dim (charset-dimension (char-charset code))) - dest) - (while (> dim 0) - (setq dest (cons (logand code 127) dest) - dim (1- dim) - code (lsh code -7)) - ) - dest)) - -(defun mule-caesar-region (start end &optional stride-ascii) - "Caesar rotation of current region. -Optional argument STRIDE-ASCII is rotation-size for Latin alphabet -\(A-Z and a-z). For non-ASCII text, ROT-N/2 will be performed in any -case (N=charset-chars; 94 for 94 or 94x94 graphic character set; 96 -for 96 or 96x96 graphic character set)." - (interactive "r\nP") - (setq stride-ascii (if stride-ascii - (mod stride-ascii 26) - 13)) - (save-excursion - (save-restriction - (narrow-to-region start end) - (goto-char start) - (while (< (point)(point-max)) - (let* ((chr (char-after (point))) - (charset (char-charset chr)) - ) - (if (eq charset 'ascii) - (cond ((and (<= ?A chr) (<= chr ?Z)) - (setq chr (+ chr stride-ascii)) - (if (> chr ?Z) - (setq chr (- chr 26)) - ) - (delete-char 1) - (insert chr) - ) - ((and (<= ?a chr) (<= chr ?z)) - (setq chr (+ chr stride-ascii)) - (if (> chr ?z) - (setq chr (- chr 26)) - ) - (delete-char 1) - (insert chr) - ) - (t - (forward-char) - )) - (let* ((stride (lsh (charset-chars charset) -1)) - (ret (mapcar (function - (lambda (octet) - (if (< octet 80) - (+ octet stride) - (- octet stride) - ))) - (char-to-octet-list chr)))) - (delete-char 1) - (insert (make-char (char-charset chr) - (car ret)(car (cdr ret)))) - ))))))) - - -(provide 'mule-caesar) - -;;; mule-caesar.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/richtext.el --- a/lisp/apel/richtext.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -;;; richtext.el -- read and save files in text/richtext format - -;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Created: 1995/7/15 -;; Version: $Id: richtext.el,v 1.2 1997/06/29 23:12:06 steve Exp $ -;; Keywords: wp, faces, MIME, multimedia - -;; This file is not part of GNU Emacs yet. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(require 'enriched) - - -;;; @ variables -;;; - -(defconst richtext-initial-annotation - (lambda () - (format "Content-Type: text/richtext\nText-Width: %d\n\n" - (enriched-text-width))) - "What to insert at the start of a text/richtext file. -If this is a string, it is inserted. If it is a list, it should be a lambda -expression, which is evaluated to get the string to insert.") - -(defconst richtext-annotation-regexp - "[ \t\n]*\\(<\\(/\\)?\\([-A-za-z0-9]+\\)>\\)[ \t\n]*" - "Regular expression matching richtext annotations.") - -(defconst richtext-translations - '((face (bold-italic "bold" "italic") - (bold "bold") - (italic "italic") - (underline "underline") - (fixed "fixed") - (excerpt "excerpt") - (default ) - (nil enriched-encode-other-face)) - (invisible (t "comment")) - (left-margin (4 "indent")) - (right-margin (4 "indentright")) - (justification (right "flushright") - (left "flushleft") - (full "flushboth") - (center "center")) - ;; The following are not part of the standard: - (FUNCTION (enriched-decode-foreground "x-color") - (enriched-decode-background "x-bg-color")) - (read-only (t "x-read-only")) - (unknown (nil format-annotate-value)) -; (font-size (2 "bigger") ; unimplemented -; (-2 "smaller")) -) - "List of definitions of text/richtext annotations. -See `format-annotate-region' and `format-deannotate-region' for the definition -of this structure.") - - -;;; @ encoder -;;; - -;;;###autoload -(defun richtext-encode (from to) - (if enriched-verbose (message "Richtext: encoding document...")) - (save-restriction - (narrow-to-region from to) - (delete-to-left-margin) - (unjustify-region) - (goto-char from) - (format-replace-strings '(("<" . ""))) - (format-insert-annotations - (format-annotate-region from (point-max) richtext-translations - 'enriched-make-annotation enriched-ignore)) - (goto-char from) - (insert (if (stringp enriched-initial-annotation) - richtext-initial-annotation - (funcall richtext-initial-annotation))) - (enriched-map-property-regions 'hard - (lambda (v b e) - (goto-char b) - (if (eolp) - (while (search-forward "\n" nil t) - (replace-match "\n") - ))) - (point) nil) - (if enriched-verbose (message nil)) - ;; Return new end. - (point-max))) - - -;;; @ decoder -;;; - -(defun richtext-next-annotation () - "Find and return next text/richtext annotation. -Return value is \(begin end name positive-p), or nil if none was found." - (catch 'tag - (while (re-search-forward richtext-annotation-regexp nil t) - (let* ((beg0 (match-beginning 0)) - (end0 (match-end 0)) - (beg (match-beginning 1)) - (end (match-end 1)) - (name (downcase (buffer-substring - (match-beginning 3) (match-end 3)))) - (pos (not (match-beginning 2))) - ) - (cond ((equal name "lt") - (delete-region beg end) - (goto-char beg) - (insert "<") - ) - ((equal name "comment") - (if pos - (throw 'tag (list beg0 end name pos)) - (throw 'tag (list beg end0 name pos)) - ) - ) - (t - (throw 'tag (list beg end name pos)) - )) - )))) - -;;;###autoload -(defun richtext-decode (from to) - (if enriched-verbose (message "Richtext: decoding document...")) - (save-excursion - (save-restriction - (narrow-to-region from to) - (goto-char from) - (let ((file-width (enriched-get-file-width)) - (use-hard-newlines t)) - (enriched-remove-header) - - (goto-char from) - (while (re-search-forward "\n\n+" nil t) - (replace-match "\n") - ) - - ;; Deal with newlines - (goto-char from) - (while (re-search-forward "[ \t\n]*[ \t\n]*" nil t) - (replace-match "\n") - (put-text-property (match-beginning 0) (point) 'hard t) - (put-text-property (match-beginning 0) (point) 'front-sticky nil) - ) - - ;; Translate annotations - (format-deannotate-region from (point-max) richtext-translations - 'richtext-next-annotation) - - ;; Fill paragraphs - (if (and file-width ; possible reasons not to fill: - (= file-width (enriched-text-width))) ; correct wd. - ;; Minimally, we have to insert indentation and justification. - (enriched-insert-indentation) - (if enriched-verbose (message "Filling paragraphs...")) - (fill-region (point-min) (point-max)))) - (if enriched-verbose (message nil)) - (point-max)))) - - -;;; @ end -;;; - -(provide 'richtext) - -;;; richtext.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/std11-parse.el --- a/lisp/apel/std11-parse.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,442 +0,0 @@ -;;; std11-parse.el --- STD 11 parser for GNU Emacs - -;; Copyright (C) 1995,1996 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Keywords: mail, news, RFC 822, STD 11 -;; Version: -;; $Id: std11-parse.el,v 1.2 1997/07/26 22:09:37 steve Exp $ - -;; This file is part of MU (Message Utilities). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(require 'std11) -(require 'emu) - - -;;; @ lexical analyze -;;; - -(defconst std11-space-chars " \t\n") -(defconst std11-spaces-regexp (concat "[" std11-space-chars "]+")) -(defconst std11-special-chars "][()<>@,;:\\<>.\"") -(defconst std11-atom-regexp - (concat "^[^" std11-special-chars std11-space-chars "]+")) - -(defun std11-analyze-spaces (string) - (if (and (string-match std11-spaces-regexp string) - (= (match-beginning 0) 0)) - (let ((end (match-end 0))) - (cons (cons 'spaces (substring string 0 end)) - (substring string end) - )))) - -(defun std11-analyze-special (str) - (if (and (> (length str) 0) - (find (aref str 0) std11-special-chars) - ) - (cons (cons 'specials (substring str 0 1)) - (substring str 1) - ))) - -(defun std11-analyze-atom (str) - (if (string-match std11-atom-regexp str) - (let ((end (match-end 0))) - (cons (cons 'atom (substring str 0 end)) - (substring str end) - )))) - -(defun std11-check-enclosure (str open close &optional recursive from) - (let ((len (length str)) - (i (or from 0)) - ) - (if (and (> len i) - (eq (aref str i) open)) - (let (p chr) - (setq i (1+ i)) - (catch 'tag - (while (< i len) - (setq chr (aref str i)) - (cond ((eq chr ?\\) - (setq i (1+ i)) - (if (>= i len) - (throw 'tag nil) - ) - (setq i (1+ i)) - ) - ((eq chr close) - (throw 'tag (1+ i)) - ) - ((eq chr open) - (if (and recursive - (setq p (std11-check-enclosure - str open close recursive i)) - ) - (setq i p) - (throw 'tag nil) - )) - (t - (setq i (1+ i)) - )) - )))))) - -(defun std11-analyze-quoted-string (str) - (let ((p (std11-check-enclosure str ?\" ?\"))) - (if p - (cons (cons 'quoted-string (substring str 1 (1- p))) - (substring str p)) - ))) - -(defun std11-analyze-domain-literal (str) - (let ((p (std11-check-enclosure str ?\[ ?\]))) - (if p - (cons (cons 'domain-literal (substring str 1 (1- p))) - (substring str p)) - ))) - -(defun std11-analyze-comment (str) - (let ((p (std11-check-enclosure str ?\( ?\) t))) - (if p - (cons (cons 'comment (substring str 1 (1- p))) - (substring str p)) - ))) - -(defun std11-lexical-analyze (str) - (let (dest ret) - (while (not (string-equal str "")) - (setq ret - (or (std11-analyze-quoted-string str) - (std11-analyze-domain-literal str) - (std11-analyze-comment str) - (std11-analyze-spaces str) - (std11-analyze-special str) - (std11-analyze-atom str) - '((error) . "") - )) - (setq dest (cons (car ret) dest)) - (setq str (cdr ret)) - ) - (nreverse dest) - )) - - -;;; @ parser -;;; - -(defun std11-ignored-token-p (token) - (let ((type (car token))) - (or (eq type 'spaces)(eq type 'comment)) - )) - -(defun std11-parse-token (lal) - (let (token itl) - (while (and lal - (progn - (setq token (car lal)) - (std11-ignored-token-p token) - )) - (setq lal (cdr lal)) - (setq itl (cons token itl)) - ) - (cons (nreverse (cons token itl)) - (cdr lal)) - )) - -(defun std11-parse-ascii-token (lal) - (let (token itl parsed token-value) - (while (and lal - (setq token (car lal)) - (or (std11-ignored-token-p token) - (if (and (setq token-value (cdr token)) - (find-non-ascii-charset-string token-value) - ) - (setq token nil) - ))) - (setq lal (cdr lal)) - (setq itl (cons token itl)) - ) - (if (and token - (setq parsed (nreverse (cons token itl))) - ) - (cons parsed (cdr lal)) - ))) - -(defun std11-parse-token-or-comment (lal) - (let (token itl) - (while (and lal - (progn - (setq token (car lal)) - (eq (car token) 'spaces) - )) - (setq lal (cdr lal)) - (setq itl (cons token itl)) - ) - (cons (nreverse (cons token itl)) - (cdr lal)) - )) - -(defun std11-parse-word (lal) - (let ((ret (std11-parse-ascii-token lal))) - (if ret - (let ((elt (car ret)) - (rest (cdr ret)) - ) - (if (or (assq 'atom elt) - (assq 'quoted-string elt)) - (cons (cons 'word elt) rest) - ))))) - -(defun std11-parse-word-or-comment (lal) - (let ((ret (std11-parse-token-or-comment lal))) - (if ret - (let ((elt (car ret)) - (rest (cdr ret)) - ) - (cond ((or (assq 'atom elt) - (assq 'quoted-string elt)) - (cons (cons 'word elt) rest) - ) - ((assq 'comment elt) - (cons (cons 'comment-word elt) rest) - )) - )))) - -(defun std11-parse-phrase (lal) - (let (ret phrase) - (while (setq ret (std11-parse-word-or-comment lal)) - (setq phrase (append phrase (cdr (car ret)))) - (setq lal (cdr ret)) - ) - (if phrase - (cons (cons 'phrase phrase) lal) - ))) - -(defun std11-parse-local-part (lal) - (let ((ret (std11-parse-word lal))) - (if ret - (let ((local-part (cdr (car ret))) dot) - (setq lal (cdr ret)) - (while (and (setq ret (std11-parse-ascii-token lal)) - (setq dot (car ret)) - (string-equal (cdr (assq 'specials dot)) ".") - (setq ret (std11-parse-word (cdr ret))) - (setq local-part - (append local-part dot (cdr (car ret))) - ) - (setq lal (cdr ret)) - )) - (cons (cons 'local-part local-part) lal) - )))) - -(defun std11-parse-sub-domain (lal) - (let ((ret (std11-parse-ascii-token lal))) - (if ret - (let ((sub-domain (car ret))) - (if (or (assq 'atom sub-domain) - (assq 'domain-literal sub-domain) - ) - (cons (cons 'sub-domain sub-domain) - (cdr ret) - ) - ))))) - -(defun std11-parse-domain (lal) - (let ((ret (std11-parse-sub-domain lal))) - (if ret - (let ((domain (cdr (car ret))) dot) - (setq lal (cdr ret)) - (while (and (setq ret (std11-parse-ascii-token lal)) - (setq dot (car ret)) - (string-equal (cdr (assq 'specials dot)) ".") - (setq ret (std11-parse-sub-domain (cdr ret))) - (setq domain - (append domain dot (cdr (car ret))) - ) - (setq lal (cdr ret)) - )) - (cons (cons 'domain domain) lal) - )))) - -(defun std11-parse-at-domain (lal) - (let ((ret (std11-parse-ascii-token lal)) at-sign) - (if (and ret - (setq at-sign (car ret)) - (string-equal (cdr (assq 'specials at-sign)) "@") - (setq ret (std11-parse-domain (cdr ret))) - ) - (cons (cons 'at-domain (append at-sign (cdr (car ret)))) - (cdr ret)) - ))) - -(defun std11-parse-addr-spec (lal) - (let ((ret (std11-parse-local-part lal)) - addr) - (if (and ret - (prog1 - (setq addr (cdr (car ret))) - (setq lal (cdr ret)) - (and (setq ret (std11-parse-at-domain lal)) - (setq addr (append addr (cdr (car ret)))) - (setq lal (cdr ret)) - ))) - (cons (cons 'addr-spec addr) lal) - ))) - -(defun std11-parse-route (lal) - (let ((ret (std11-parse-at-domain lal)) - route comma colon) - (if (and ret - (progn - (setq route (cdr (car ret))) - (setq lal (cdr ret)) - (while (and (setq ret (std11-parse-ascii-token lal)) - (setq comma (car ret)) - (string-equal (cdr (assq 'specials comma)) ",") - (setq ret (std11-parse-at-domain (cdr ret))) - ) - (setq route (append route comma (cdr (car ret)))) - (setq lal (cdr ret)) - ) - (and (setq ret (std11-parse-ascii-token lal)) - (setq colon (car ret)) - (string-equal (cdr (assq 'specials colon)) ":") - (setq route (append route colon)) - ) - )) - (cons (cons 'route route) - (cdr ret) - ) - ))) - -(defun std11-parse-route-addr (lal) - (let ((ret (std11-parse-ascii-token lal)) - < route addr-spec >) - (if (and ret - (setq < (car ret)) - (string-equal (cdr (assq 'specials <)) "<") - (setq lal (cdr ret)) - (progn (and (setq ret (std11-parse-route lal)) - (setq route (cdr (car ret))) - (setq lal (cdr ret)) - ) - (setq ret (std11-parse-addr-spec lal)) - ) - (setq addr-spec (cdr (car ret))) - (setq lal (cdr ret)) - (setq ret (std11-parse-ascii-token lal)) - (setq > (car ret)) - (string-equal (cdr (assq 'specials >)) ">") - ) - (cons (cons 'route-addr (append route addr-spec)) - (cdr ret) - ) - ))) - -(defun std11-parse-phrase-route-addr (lal) - (let ((ret (std11-parse-phrase lal)) phrase) - (if ret - (progn - (setq phrase (cdr (car ret))) - (setq lal (cdr ret)) - )) - (if (setq ret (std11-parse-route-addr lal)) - (cons (list 'phrase-route-addr - phrase - (cdr (car ret))) - (cdr ret)) - ))) - -(defun std11-parse-mailbox (lal) - (let ((ret (or (std11-parse-phrase-route-addr lal) - (std11-parse-addr-spec lal))) - mbox comment) - (if (and ret - (prog1 - (setq mbox (car ret)) - (setq lal (cdr ret)) - (if (and (setq ret (std11-parse-token-or-comment lal)) - (setq comment (cdr (assq 'comment (car ret)))) - ) - (setq lal (cdr ret)) - ))) - (cons (list 'mailbox mbox comment) - lal) - ))) - -(defun std11-parse-group (lal) - (let ((ret (std11-parse-phrase lal)) - phrase colon comma mbox semicolon) - (if (and ret - (setq phrase (cdr (car ret))) - (setq lal (cdr ret)) - (setq ret (std11-parse-ascii-token lal)) - (setq colon (car ret)) - (string-equal (cdr (assq 'specials colon)) ":") - (setq lal (cdr ret)) - (progn - (and (setq ret (std11-parse-mailbox lal)) - (setq mbox (list (car ret))) - (setq lal (cdr ret)) - (progn - (while (and (setq ret (std11-parse-ascii-token lal)) - (setq comma (car ret)) - (string-equal - (cdr (assq 'specials comma)) ",") - (setq lal (cdr ret)) - (setq ret (std11-parse-mailbox lal)) - (setq mbox (cons (car ret) mbox)) - (setq lal (cdr ret)) - ) - ))) - (and (setq ret (std11-parse-ascii-token lal)) - (setq semicolon (car ret)) - (string-equal (cdr (assq 'specials semicolon)) ";") - ))) - (cons (list 'group phrase (nreverse mbox)) - (cdr ret) - ) - ))) - -(defun std11-parse-address (lal) - (or (std11-parse-group lal) - (std11-parse-mailbox lal) - )) - -(defun std11-parse-addresses (lal) - (let ((ret (std11-parse-address lal))) - (if ret - (let ((dest (list (car ret)))) - (setq lal (cdr ret)) - (while (and (setq ret (std11-parse-ascii-token lal)) - (string-equal (cdr (assq 'specials (car ret))) ",") - (setq ret (std11-parse-address (cdr ret))) - ) - (setq dest (cons (car ret) dest)) - (setq lal (cdr ret)) - ) - (nreverse dest) - )))) - - -;;; @ end -;;; - -(provide 'std11-parse) - -;;; std11-parse.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/std11.el --- a/lisp/apel/std11.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,373 +0,0 @@ -;;; std11.el --- STD 11 functions for GNU Emacs - -;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc. - -;; Author: MORIOKA Tomohiko -;; Keywords: mail, news, RFC 822, STD 11 -;; Version: $Id: std11.el,v 1.1 1997/06/03 04:18:36 steve Exp $ - -;; This file is part of MU (Message Utilities). - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 2, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Code: - -(autoload 'buffer-substring-no-properties "emu") -(autoload 'member "emu") - - -;;; @ field -;;; - -(defconst std11-field-name-regexp "[!-9;-~]+") -(defconst std11-field-head-regexp - (concat "^" std11-field-name-regexp ":")) -(defconst std11-next-field-head-regexp - (concat "\n" std11-field-name-regexp ":")) - -(defun std11-field-end () - "Move to end of field and return this point. [std11.el]" - (if (re-search-forward std11-next-field-head-regexp nil t) - (goto-char (match-beginning 0)) - (if (re-search-forward "^$" nil t) - (goto-char (1- (match-beginning 0))) - (end-of-line) - )) - (point) - ) - -(defun std11-field-body (name &optional boundary) - "Return body of field NAME. -If BOUNDARY is not nil, it is used as message header separator. -\[std11.el]" - (save-excursion - (save-restriction - (std11-narrow-to-header boundary) - (goto-char (point-min)) - (let ((case-fold-search t)) - (if (re-search-forward (concat "^" name ":[ \t]*") nil t) - (buffer-substring-no-properties (match-end 0) (std11-field-end)) - ))))) - -(defun std11-find-field-body (field-names &optional boundary) - "Return the first found field-body specified by FIELD-NAMES -of the message header in current buffer. If BOUNDARY is not nil, it is -used as message header separator. [std11.el]" - (save-excursion - (save-restriction - (std11-narrow-to-header boundary) - (let ((case-fold-search t) - field-name) - (catch 'tag - (while (setq field-name (car field-names)) - (goto-char (point-min)) - (if (re-search-forward (concat "^" field-name ":[ \t]*") nil t) - (throw 'tag - (buffer-substring-no-properties - (match-end 0) (std11-field-end))) - ) - (setq field-names (cdr field-names)) - )))))) - -(defun std11-field-bodies (field-names &optional default-value boundary) - "Return list of each field-bodies of FIELD-NAMES of the message header -in current buffer. If BOUNDARY is not nil, it is used as message -header separator. [std11.el]" - (save-excursion - (save-restriction - (std11-narrow-to-header boundary) - (let* ((case-fold-search t) - (dest (make-list (length field-names) default-value)) - (s-rest field-names) - (d-rest dest) - field-name) - (while (setq field-name (car s-rest)) - (goto-char (point-min)) - (if (re-search-forward (concat "^" field-name ":[ \t]*") nil t) - (setcar d-rest - (buffer-substring-no-properties - (match-end 0) (std11-field-end))) - ) - (setq s-rest (cdr s-rest) - d-rest (cdr d-rest)) - ) - dest)))) - - -;;; @ unfolding -;;; - -(defun std11-unfold-string (string) - "Unfold STRING as message header field. [std11.el]" - (let ((dest "")) - (while (string-match "\n\\([ \t]\\)" string) - (setq dest (concat dest - (substring string 0 (match-beginning 0)) - (match-string 1 string) - )) - (setq string (substring string (match-end 0))) - ) - (concat dest string) - )) - - -;;; @ header -;;; - -(defun std11-narrow-to-header (&optional boundary) - "Narrow to the message header. -If BOUNDARY is not nil, it is used as message header separator. -\[std11.el]" - (narrow-to-region - (goto-char (point-min)) - (if (re-search-forward - (concat "^\\(" (regexp-quote (or boundary "")) "\\)?$") - nil t) - (match-beginning 0) - (point-max) - ))) - -(defun std11-header-string (regexp &optional boundary) - "Return string of message header fields matched by REGEXP. -If BOUNDARY is not nil, it is used as message header separator. -\[std11.el]" - (let ((case-fold-search t)) - (save-excursion - (save-restriction - (std11-narrow-to-header boundary) - (goto-char (point-min)) - (let (field header) - (while (re-search-forward std11-field-head-regexp nil t) - (setq field - (buffer-substring (match-beginning 0) (std11-field-end))) - (if (string-match regexp field) - (setq header (concat header field "\n")) - )) - header) - )))) - -(defun std11-header-string-except (regexp &optional boundary) - "Return string of message header fields not matched by REGEXP. -If BOUNDARY is not nil, it is used as message header separator. -\[std11.el]" - (let ((case-fold-search t)) - (save-excursion - (save-restriction - (std11-narrow-to-header boundary) - (goto-char (point-min)) - (let (field header) - (while (re-search-forward std11-field-head-regexp nil t) - (setq field - (buffer-substring (match-beginning 0) (std11-field-end))) - (if (not (string-match regexp field)) - (setq header (concat header field "\n")) - )) - header) - )))) - -(defun std11-collect-field-names (&optional boundary) - "Return list of all field-names of the message header in current buffer. -If BOUNDARY is not nil, it is used as message header separator. -\[std11.el]" - (save-excursion - (save-restriction - (std11-narrow-to-header boundary) - (goto-char (point-min)) - (let (dest name) - (while (re-search-forward std11-field-head-regexp nil t) - (setq name (buffer-substring-no-properties - (match-beginning 0)(1- (match-end 0)))) - (or (member name dest) - (setq dest (cons name dest)) - ) - ) - dest)))) - - -;;; @ quoted-string -;;; - -(defun std11-wrap-as-quoted-pairs (string specials) - (let (dest - (i 0) - (b 0) - (len (length string)) - ) - (while (< i len) - (let ((chr (aref string i))) - (if (memq chr specials) - (setq dest (concat dest (substring string b i) "\\") - b i) - )) - (setq i (1+ i)) - ) - (concat dest (substring string b)) - )) - -(defconst std11-non-qtext-char-list '(?\" ?\\ ?\r ?\n)) - -(defun std11-wrap-as-quoted-string (string) - "Wrap STRING as RFC 822 quoted-string. [std11.el]" - (concat "\"" - (std11-wrap-as-quoted-pairs string std11-non-qtext-char-list) - "\"")) - -(defun std11-strip-quoted-pair (string) - "Strip quoted-pairs in STRING. [std11.el]" - (let (dest - (b 0) - (i 0) - (len (length string)) - ) - (while (< i len) - (let ((chr (aref string i))) - (if (eq chr ?\\) - (setq dest (concat dest (substring string b i)) - b (1+ i) - i (+ i 2)) - (setq i (1+ i)) - ))) - (concat dest (substring string b)) - )) - -(defun std11-strip-quoted-string (string) - "Strip quoted-string STRING. [std11.el]" - (let ((len (length string))) - (or (and (>= len 2) - (let ((max (1- len))) - (and (eq (aref string 0) ?\") - (eq (aref string max) ?\") - (std11-strip-quoted-pair (substring string 1 max)) - ))) - string))) - - -;;; @ composer -;;; - -(defun std11-addr-to-string (seq) - "Return string from lexical analyzed list SEQ -represents addr-spec of RFC 822. [std11.el]" - (mapconcat (function - (lambda (token) - (let ((name (car token))) - (cond - ((eq name 'spaces) "") - ((eq name 'comment) "") - ((eq name 'quoted-string) - (concat "\"" (cdr token) "\"")) - (t (cdr token))) - ))) - seq "") - ) - -(defun std11-address-string (address) - "Return string of address part from parsed ADDRESS of RFC 822. -\[std11.el]" - (cond ((eq (car address) 'group) - (mapconcat (function std11-address-string) - (car (cdr address)) - ", ") - ) - ((eq (car address) 'mailbox) - (let ((addr (nth 1 address))) - (std11-addr-to-string - (if (eq (car addr) 'phrase-route-addr) - (nth 2 addr) - (cdr addr) - ) - ))))) - -(defun std11-full-name-string (address) - "Return string of full-name part from parsed ADDRESS of RFC 822. -\[std11.el]" - (cond ((eq (car address) 'group) - (mapconcat (function - (lambda (token) - (cdr token) - )) - (nth 1 address) "") - ) - ((eq (car address) 'mailbox) - (let ((addr (nth 1 address)) - (comment (nth 2 address)) - phrase) - (if (eq (car addr) 'phrase-route-addr) - (setq phrase - (mapconcat - (function - (lambda (token) - (let ((type (car token))) - (cond ((eq type 'quoted-string) - (std11-strip-quoted-pair (cdr token)) - ) - ((eq type 'comment) - (concat - "(" - (std11-strip-quoted-pair (cdr token)) - ")") - ) - (t - (cdr token) - ))))) - (nth 1 addr) "")) - ) - (cond ((> (length phrase) 0) phrase) - (comment (std11-strip-quoted-pair comment)) - ) - )))) - - -;;; @ parser -;;; - -(defun std11-parse-address-string (string) - "Parse STRING as mail address. [std11.el]" - (std11-parse-address (std11-lexical-analyze string)) - ) - -(defun std11-parse-addresses-string (string) - "Parse STRING as mail address list. [std11.el]" - (std11-parse-addresses (std11-lexical-analyze string)) - ) - -(defun std11-extract-address-components (string) - "Extract full name and canonical address from STRING. -Returns a list of the form (FULL-NAME CANONICAL-ADDRESS). -If no name can be extracted, FULL-NAME will be nil. [std11.el]" - (let* ((structure (car (std11-parse-address-string - (std11-unfold-string string)))) - (phrase (std11-full-name-string structure)) - (address (std11-address-string structure)) - ) - (list phrase address) - )) - -(provide 'std11) - -(mapcar (function - (lambda (func) - (autoload func "std11-parse") - )) - '(std11-lexical-analyze - std11-parse-address std11-parse-addresses - std11-parse-address-string)) - - -;;; @ end -;;; - -;;; std11.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/apel/tinyrich.el --- a/lisp/apel/tinyrich.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -;;; -;;; $Id: tinyrich.el,v 1.2 1997/07/26 22:09:38 steve Exp $ -;;; -;;; by MORIOKA Tomohiko -;;; modified by YAMATE Keiichirou -;;; - -(defvar mime-viewer/face-list-for-text/enriched - (cond ((and (>= emacs-major-version 19) window-system) - '(bold italic fixed underline) - ) - ((and (boundp 'NEMACS) NEMACS) - '("bold" "italic" "underline") - ))) - -(defun enriched-decode (beg end) - (interactive "*r") - (save-excursion - (save-restriction - (narrow-to-region beg end) - (goto-char beg) - (while (re-search-forward "[ \t]*\\(\n+\\)[ \t]*" nil t) - (let ((str (buffer-substring (match-beginning 1) - (match-end 1)))) - (if (string= str "\n") - (replace-match " ") - (replace-match (substring str 1)) - ))) - (goto-char beg) - (let (cmd sym str (fb (point)) fe b e) - (while (re-search-forward "<\\(<\\|[^<>\n\r \t]+>\\)" nil t) - (setq b (match-beginning 0)) - (setq cmd (buffer-substring b (match-end 0))) - (if (string= cmd "<<") - (replace-match "<") - (replace-match "") - (setq cmd (downcase (substring cmd 1 (- (length cmd) 1)))) - ) - (setq sym (intern cmd)) - (cond ((eq sym 'param) - (setq b (point)) - (save-excursion - (save-restriction - (if (search-forward "" nil t) - (progn - (replace-match "") - (setq e (point)) - ) - (setq e end) - ))) - (delete-region b e) - ) - ((memq sym mime-viewer/face-list-for-text/enriched) - (setq b (point)) - (save-excursion - (save-restriction - (if (re-search-forward (concat "") nil t) - (progn - (replace-match "") - (setq e (point)) - ) - (setq e end) - ))) - (tm:set-face-region b e sym) - ))) - (goto-char (point-max)) - (if (not (eq (preceding-char) ?\n)) - (insert "\n") - ) - )))) - - -;;; @ text/richtext <-> text/enriched converter -;;; - -(defun richtext-to-enriched-region (beg end) - "Convert the region of text/richtext style to text/enriched style." - (save-excursion - (save-restriction - (narrow-to-region beg end) - (goto-char (point-min)) - (let (b e i) - (while (re-search-forward "[ \t]*" nil t) - (setq b (match-beginning 0)) - (delete-region b - (if (re-search-forward "[ \t]*" nil t) - (match-end 0) - (point-max) - )) - ) - (goto-char (point-min)) - (while (re-search-forward "\n\n+" nil t) - (replace-match "\n") - ) - (goto-char (point-min)) - (while (re-search-forward "[ \t\n]*[ \t\n]*" nil t) - (setq b (match-beginning 0)) - (setq e (match-end 0)) - (setq i 1) - (while (looking-at "[ \t\n]*[ \t\n]*") - (setq e (match-end 0)) - (setq i (1+ i)) - (goto-char e) - ) - (delete-region b e) - (while (>= i 0) - (insert "\n") - (setq i (1- i)) - )) - (goto-char (point-min)) - (while (search-forward "" nil t) - (replace-match "<<") - ) - )))) - -(defun enriched-to-richtext-region (beg end) - "Convert the region of text/enriched style to text/richtext style." - (save-excursion - (save-restriction - (goto-char beg) - (and (search-forward "text/enriched") - (replace-match "text/richtext")) - (search-forward "\n\n") - (narrow-to-region (match-end 0) end) - (let (str n) - (goto-char (point-min)) - (while (re-search-forward "\n\n+" nil t) - (setq str (buffer-substring (match-beginning 0) - (match-end 0))) - (setq n (1- (length str))) - (setq str "") - (while (> n 0) - (setq str (concat str "\n")) - (setq n (1- n)) - ) - (replace-match str) - ) - (goto-char (point-min)) - (while (search-forward "<<" nil t) - (replace-match "") - ) - )))) - - -;;; @ encoder and decoder -;;; - -(defun richtext-decode (beg end) - (save-restriction - (narrow-to-region beg end) - (richtext-to-enriched-region beg (point-max)) - (enriched-decode beg (point-max)) - )) - -;; (defun richtext-encode (beg end) -;; (save-restriction -;; (narrow-to-region beg end) -;; (enriched-encode beg (point-max)) -;; (enriched-to-richtext-region beg (point-max)) -;; )) - - -;;; @ end -;;; - -(provide 'tinyrich) diff -r f427b8ec4379 -r 41ff10fd062f lisp/auto-autoloads.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/auto-autoloads.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,638 @@ +;;; DO NOT MODIFY THIS FILE +(if (featurep 'TopLevel-autoloads) (error "Already loaded")) + +;;;### (autoloads (batch-byte-recompile-directory batch-byte-recompile-directory-norecurse batch-byte-compile display-call-tree byte-compile-sexp byte-compile compile-defun byte-compile-file byte-recompile-file byte-recompile-directory byte-force-recompile) "bytecomp" "lisp/bytecomp.el") + +(autoload 'byte-force-recompile "bytecomp" "\ +Recompile every `.el' file in DIRECTORY that already has a `.elc' file. +Files in subdirectories of DIRECTORY are processed also." t nil) + +(autoload 'byte-recompile-directory "bytecomp" "\ +Recompile every `.el' file in DIRECTORY that needs recompilation. +This is if a `.elc' file exists but is older than the `.el' file. +Files in subdirectories of DIRECTORY are processed also unless argument +NORECURSION is non-nil. + +If the `.elc' file does not exist, normally the `.el' file is *not* compiled. +But a prefix argument (optional second arg) means ask user, +for each such `.el' file, whether to compile it. Prefix argument 0 means +don't ask and compile the file anyway. + +A nonzero prefix argument also means ask about each subdirectory. + +If the fourth argument FORCE is non-nil, +recompile every `.el' file that already has a `.elc' file." t nil) + +(autoload 'byte-recompile-file "bytecomp" "\ +Recompile a file of Lisp code named FILENAME if it needs recompilation. +This is if the `.elc' file exists but is older than the `.el' file. + +If the `.elc' file does not exist, normally the `.el' file is *not* +compiled. But a prefix argument (optional second arg) means ask user +whether to compile it. Prefix argument 0 don't ask and recompile anyway." t nil) + +(autoload 'byte-compile-file "bytecomp" "\ +Compile a file of Lisp code named FILENAME into a file of byte code. +The output file's name is made by appending `c' to the end of FILENAME. +With prefix arg (noninteractively: 2nd arg), load the file after compiling." t nil) + +(autoload 'compile-defun "bytecomp" "\ +Compile and evaluate the current top-level form. +Print the result in the minibuffer. +With argument, insert value in current buffer after the form." t nil) + +(autoload 'byte-compile "bytecomp" "\ +If FORM is a symbol, byte-compile its function definition. +If FORM is a lambda or a macro, byte-compile it as a function." nil nil) + +(autoload 'byte-compile-sexp "bytecomp" "\ +Compile and return SEXP." nil nil) + +(autoload 'display-call-tree "bytecomp" "\ +Display a call graph of a specified file. +This lists which functions have been called, what functions called +them, and what functions they call. The list includes all functions +whose definitions have been compiled in this Emacs session, as well as +all functions called by those functions. + +The call graph does not include macros, inline functions, or +primitives that the byte-code interpreter knows about directly (eq, +cons, etc.). + +The call tree also lists those functions which are not known to be called +\(that is, to which no calls have been compiled), and which cannot be +invoked interactively." t nil) + +(autoload 'batch-byte-compile "bytecomp" "\ +Run `byte-compile-file' on the files remaining on the command line. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. +Each file is processed even if an error occurred previously. +For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\"" nil nil) + +(autoload 'batch-byte-recompile-directory-norecurse "bytecomp" "\ +Same as `batch-byte-recompile-directory' but without recursion." nil nil) + +(autoload 'batch-byte-recompile-directory "bytecomp" "\ +Runs `byte-recompile-directory' on the dirs remaining on the command line. +Must be used only with `-batch', and kills Emacs on completion. +For example, invoke `xemacs -batch -f batch-byte-recompile-directory .'." nil nil) + +;;;*** + +;;;### (autoloads (compiler-macroexpand define-compiler-macro ignore-errors assert check-type typep deftype cl-struct-setf-expander defstruct define-modify-macro callf2 callf letf* letf rotatef shiftf remf cl-do-pop psetf setf get-setf-method defsetf define-setf-method declare the locally multiple-value-setq multiple-value-bind lexical-let* lexical-let symbol-macrolet macrolet labels flet progv psetq do-all-symbols do-symbols dotimes dolist do* do loop return-from return block etypecase typecase ecase case load-time-value eval-when destructuring-bind function* defmacro* defun* gentemp gensym cl-compile-time-init) "cl-macs" "lisp/cl-macs.el") + +(autoload 'cl-compile-time-init "cl-macs" nil nil nil) + +(autoload 'gensym "cl-macs" "\ +Generate a new uninterned symbol. +The name is made by appending a number to PREFIX, default \"G\"." nil nil) + +(autoload 'gentemp "cl-macs" "\ +Generate a new interned symbol with a unique name. +The name is made by appending a number to PREFIX, default \"G\"." nil nil) + +(autoload 'defun* "cl-macs" "\ +(defun* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. +Like normal `defun', except ARGLIST allows full Common Lisp conventions, +and BODY is implicitly surrounded by (block NAME ...)." nil 'macro) + +(autoload 'defmacro* "cl-macs" "\ +(defmacro* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a macro. +Like normal `defmacro', except ARGLIST allows full Common Lisp conventions, +and BODY is implicitly surrounded by (block NAME ...)." nil 'macro) + +(autoload 'function* "cl-macs" "\ +(function* SYMBOL-OR-LAMBDA): introduce a function. +Like normal `function', except that if argument is a lambda form, its +ARGLIST allows full Common Lisp conventions." nil 'macro) + +(autoload 'destructuring-bind "cl-macs" nil nil 'macro) + +(autoload 'eval-when "cl-macs" "\ +(eval-when (WHEN...) BODY...): control when BODY is evaluated. +If `compile' is in WHEN, BODY is evaluated when compiled at top-level. +If `load' is in WHEN, BODY is evaluated when loaded after top-level compile. +If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level." nil 'macro) + +(autoload 'load-time-value "cl-macs" "\ +Like `progn', but evaluates the body at load time. +The result of the body appears to the compiler as a quoted constant." nil 'macro) + +(autoload 'case "cl-macs" "\ +(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. +Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared +against each key in each KEYLIST; the corresponding BODY is evaluated. +If no clause succeeds, case returns nil. A single atom may be used in +place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is +allowed only in the final clause, and matches if no other keys match. +Key values are compared by `eql'." nil 'macro) + +(autoload 'ecase "cl-macs" "\ +(ecase EXPR CLAUSES...): like `case', but error if no case fits. +`otherwise'-clauses are not allowed." nil 'macro) + +(autoload 'typecase "cl-macs" "\ +(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. +Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it +satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, +typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the +final clause, and matches if no other keys match." nil 'macro) + +(autoload 'etypecase "cl-macs" "\ +(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits. +`otherwise'-clauses are not allowed." nil 'macro) + +(autoload 'block "cl-macs" "\ +(block NAME BODY...): define a lexically-scoped block named NAME. +NAME may be any symbol. Code inside the BODY forms can call `return-from' +to jump prematurely out of the block. This differs from `catch' and `throw' +in two respects: First, the NAME is an unevaluated symbol rather than a +quoted symbol or other form; and second, NAME is lexically rather than +dynamically scoped: Only references to it within BODY will work. These +references may appear inside macro expansions, but not inside functions +called from BODY." nil 'macro) + +(autoload 'return "cl-macs" "\ +(return [RESULT]): return from the block named nil. +This is equivalent to `(return-from nil RESULT)'." nil 'macro) + +(autoload 'return-from "cl-macs" "\ +(return-from NAME [RESULT]): return from the block named NAME. +This jump out to the innermost enclosing `(block NAME ...)' form, +returning RESULT from that form (or nil if RESULT is omitted). +This is compatible with Common Lisp, but note that `defun' and +`defmacro' do not create implicit blocks as they do in Common Lisp." nil 'macro) + +(autoload 'loop "cl-macs" "\ +(loop CLAUSE...): The Common Lisp `loop' macro. +Valid clauses are: + for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, + for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, + for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, + always COND, never COND, thereis COND, collect EXPR into VAR, + append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, + count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, + if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], + unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], + do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, + finally return EXPR, named NAME." nil 'macro) + +(autoload 'do "cl-macs" "\ +The Common Lisp `do' loop. +Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" nil 'macro) + +(autoload 'do* "cl-macs" "\ +The Common Lisp `do*' loop. +Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" nil 'macro) + +(autoload 'dolist "cl-macs" "\ +(dolist (VAR LIST [RESULT]) BODY...): loop over a list. +Evaluate BODY with VAR bound to each `car' from LIST, in turn. +Then evaluate RESULT to get return value, default nil." nil 'macro) + +(autoload 'dotimes "cl-macs" "\ +(dotimes (VAR COUNT [RESULT]) BODY...): loop a certain number of times. +Evaluate BODY with VAR bound to successive integers from 0, inclusive, +to COUNT, exclusive. Then evaluate RESULT to get return value, default +nil." nil 'macro) + +(autoload 'do-symbols "cl-macs" "\ +(dosymbols (VAR [OBARRAY [RESULT]]) BODY...): loop over all symbols. +Evaluate BODY with VAR bound to each interned symbol, or to each symbol +from OBARRAY." nil 'macro) + +(autoload 'do-all-symbols "cl-macs" nil nil 'macro) + +(autoload 'psetq "cl-macs" "\ +(psetq SYM VAL SYM VAL ...): set SYMs to the values VALs in parallel. +This is like `setq', except that all VAL forms are evaluated (in order) +before assigning any symbols SYM to the corresponding values." nil 'macro) + +(autoload 'progv "cl-macs" "\ +(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY. +The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. +Each SYMBOL in the first list is bound to the corresponding VALUE in the +second list (or made unbound if VALUES is shorter than SYMBOLS); then the +BODY forms are executed and their result is returned. This is much like +a `let' form, except that the list of symbols can be computed at run-time." nil 'macro) + +(autoload 'flet "cl-macs" "\ +(flet ((FUNC ARGLIST BODY...) ...) FORM...): make temporary function defns. +This is an analogue of `let' that operates on the function cell of FUNC +rather than its value cell. The FORMs are evaluated with the specified +function definitions in place, then the definitions are undone (the FUNCs +go back to their previous definitions, or lack thereof)." nil 'macro) + +(autoload 'labels "cl-macs" "\ +(labels ((FUNC ARGLIST BODY...) ...) FORM...): make temporary func bindings. +This is like `flet', except the bindings are lexical instead of dynamic. +Unlike `flet', this macro is fully complaint with the Common Lisp standard." nil 'macro) + +(autoload 'macrolet "cl-macs" "\ +(macrolet ((NAME ARGLIST BODY...) ...) FORM...): make temporary macro defns. +This is like `flet', but for macros instead of functions." nil 'macro) + +(autoload 'symbol-macrolet "cl-macs" "\ +(symbol-macrolet ((NAME EXPANSION) ...) FORM...): make symbol macro defns. +Within the body FORMs, references to the variable NAME will be replaced +by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)." nil 'macro) + +(autoload 'lexical-let "cl-macs" "\ +(lexical-let BINDINGS BODY...): like `let', but lexically scoped. +The main visible difference is that lambdas inside BODY will create +lexical closures as in Common Lisp." nil 'macro) + +(autoload 'lexical-let* "cl-macs" "\ +(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped. +The main visible difference is that lambdas inside BODY will create +lexical closures as in Common Lisp." nil 'macro) + +(autoload 'multiple-value-bind "cl-macs" "\ +(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values. +FORM must return a list; the BODY is then executed with the first N elements +of this list bound (`let'-style) to each of the symbols SYM in turn. This +is analogous to the Common Lisp `multiple-value-bind' macro, using lists to +simulate true multiple return values. For compatibility, (values A B C) is +a synonym for (list A B C)." nil 'macro) + +(autoload 'multiple-value-setq "cl-macs" "\ +(multiple-value-setq (SYM SYM...) FORM): collect multiple return values. +FORM must return a list; the first N elements of this list are stored in +each of the symbols SYM in turn. This is analogous to the Common Lisp +`multiple-value-setq' macro, using lists to simulate true multiple return +values. For compatibility, (values A B C) is a synonym for (list A B C)." nil 'macro) + +(autoload 'locally "cl-macs" nil nil 'macro) + +(autoload 'the "cl-macs" nil nil 'macro) + +(autoload 'declare "cl-macs" nil nil 'macro) + +(autoload 'define-setf-method "cl-macs" "\ +(define-setf-method NAME ARGLIST BODY...): define a `setf' method. +This method shows how to handle `setf's to places of the form (NAME ARGS...). +The argument forms ARGS are bound according to ARGLIST, as if NAME were +going to be expanded as a macro, then the BODY forms are executed and must +return a list of five elements: a temporary-variables list, a value-forms +list, a store-variables list (of length one), a store-form, and an access- +form. See `defsetf' for a simpler way to define most setf-methods." nil 'macro) + +(autoload 'defsetf "cl-macs" "\ +(defsetf NAME FUNC): define a `setf' method. +This macro is an easy-to-use substitute for `define-setf-method' that works +well for simple place forms. In the simple `defsetf' form, `setf's of +the form (setf (NAME ARGS...) VAL) are transformed to function or macro +calls of the form (FUNC ARGS... VAL). Example: (defsetf aref aset). +Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). +Here, the above `setf' call is expanded by binding the argument forms ARGS +according to ARGLIST, binding the value form VAL to STORE, then executing +BODY, which must return a Lisp form that does the necessary `setf' operation. +Actually, ARGLIST and STORE may be bound to temporary variables which are +introduced automatically to preserve proper execution order of the arguments. +Example: (defsetf nth (n x) (v) (list 'setcar (list 'nthcdr n x) v))." nil 'macro) + +(autoload 'get-setf-method "cl-macs" "\ +Return a list of five values describing the setf-method for PLACE. +PLACE may be any Lisp form which can appear as the PLACE argument to +a macro like `setf' or `incf'." nil nil) + +(autoload 'setf "cl-macs" "\ +(setf PLACE VAL PLACE VAL ...): set each PLACE to the value of its VAL. +This is a generalized version of `setq'; the PLACEs may be symbolic +references such as (car x) or (aref x i), as well as plain symbols. +For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y). +The return value is the last VAL in the list." nil 'macro) + +(autoload 'psetf "cl-macs" "\ +(psetf PLACE VAL PLACE VAL ...): set PLACEs to the values VALs in parallel. +This is like `setf', except that all VAL forms are evaluated (in order) +before assigning any PLACEs to the corresponding values." nil 'macro) + +(autoload 'cl-do-pop "cl-macs" nil nil nil) + +(autoload 'remf "cl-macs" "\ +(remf PLACE TAG): remove TAG from property list PLACE. +PLACE may be a symbol, or any generalized variable allowed by `setf'. +The form returns true if TAG was found and removed, nil otherwise." nil 'macro) + +(autoload 'shiftf "cl-macs" "\ +(shiftf PLACE PLACE... VAL): shift left among PLACEs. +Example: (shiftf A B C) sets A to B, B to C, and returns the old A. +Each PLACE may be a symbol, or any generalized variable allowed by `setf'." nil 'macro) + +(autoload 'rotatef "cl-macs" "\ +(rotatef PLACE...): rotate left among PLACEs. +Example: (rotatef A B C) sets A to B, B to C, and C to A. It returns nil. +Each PLACE may be a symbol, or any generalized variable allowed by `setf'." nil 'macro) + +(autoload 'letf "cl-macs" "\ +(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. +This is the analogue of `let', but with generalized variables (in the +sense of `setf') for the PLACEs. Each PLACE is set to the corresponding +VALUE, then the BODY forms are executed. On exit, either normally or +because of a `throw' or error, the PLACEs are set back to their original +values. Note that this macro is *not* available in Common Lisp. +As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', +the PLACE is not modified before executing BODY." nil 'macro) + +(autoload 'letf* "cl-macs" "\ +(letf* ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. +This is the analogue of `let*', but with generalized variables (in the +sense of `setf') for the PLACEs. Each PLACE is set to the corresponding +VALUE, then the BODY forms are executed. On exit, either normally or +because of a `throw' or error, the PLACEs are set back to their original +values. Note that this macro is *not* available in Common Lisp. +As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', +the PLACE is not modified before executing BODY." nil 'macro) + +(autoload 'callf "cl-macs" "\ +(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...). +FUNC should be an unquoted function name. PLACE may be a symbol, +or any generalized variable allowed by `setf'." nil 'macro) + +(autoload 'callf2 "cl-macs" "\ +(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...). +Like `callf', but PLACE is the second argument of FUNC, not the first." nil 'macro) + +(autoload 'define-modify-macro "cl-macs" "\ +(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro. +If NAME is called, it combines its PLACE argument with the other arguments +from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" nil 'macro) + +(autoload 'defstruct "cl-macs" "\ +(defstruct (NAME OPTIONS...) (SLOT SLOT-OPTS...)...): define a struct type. +This macro defines a new Lisp data type called NAME, which contains data +stored in SLOTs. This defines a `make-NAME' constructor, a `copy-NAME' +copier, a `NAME-p' predicate, and setf-able `NAME-SLOT' accessors." nil 'macro) + +(autoload 'cl-struct-setf-expander "cl-macs" nil nil nil) + +(autoload 'deftype "cl-macs" "\ +(deftype NAME ARGLIST BODY...): define NAME as a new data type. +The type name can then be used in `typecase', `check-type', etc." nil 'macro) + +(autoload 'typep "cl-macs" "\ +Check that OBJECT is of type TYPE. +TYPE is a Common Lisp-style type specifier." nil nil) + +(autoload 'check-type "cl-macs" "\ +Verify that FORM is of type TYPE; signal an error if not. +STRING is an optional description of the desired type." nil 'macro) + +(autoload 'assert "cl-macs" "\ +Verify that FORM returns non-nil; signal an error if not. +Second arg SHOW-ARGS means to include arguments of FORM in message. +Other args STRING and ARGS... are arguments to be passed to `error'. +They are not evaluated unless the assertion fails. If STRING is +omitted, a default message listing FORM itself is used." nil 'macro) + +(autoload 'ignore-errors "cl-macs" "\ +Execute FORMS; if an error occurs, return nil. +Otherwise, return result of last FORM." nil 'macro) + +(autoload 'define-compiler-macro "cl-macs" "\ +(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro. +This is like `defmacro', but macro expansion occurs only if the call to +FUNC is compiled (i.e., not interpreted). Compiler macros should be used +for optimizing the way calls to FUNC are compiled; the form returned by +BODY should do the same thing as a call to the normal function called +FUNC, though possibly more efficiently. Note that, like regular macros, +compiler macros are expanded repeatedly until no further expansions are +possible. Unlike regular macros, BODY can decide to \"punt\" and leave the +original function call alone by declaring an initial `&whole foo' parameter +and then returning foo." nil 'macro) + +(autoload 'compiler-macroexpand "cl-macs" nil nil nil) + +;;;*** + +;;;### (autoloads (Custom-make-dependencies) "cus-dep" "lisp/cus-dep.el") + +(autoload 'Custom-make-dependencies "cus-dep" "\ +Extract custom dependencies from .el files in SUBDIRS. +SUBDIRS is a list of directories. If it is nil, the command-line +arguments are used. If it is a string, only that directory is +processed. This function is especially useful in batch mode. + +Batch usage: xemacs -batch -l cus-dep.el -f Custom-make-dependencies DIRS" t nil) + +;;;*** + +;;;### (autoloads (customize-menu-create custom-menu-create custom-save-all customize-save-customized customize-browse custom-buffer-create-other-window custom-buffer-create customize-apropos-groups customize-apropos-faces customize-apropos-options customize-apropos customize-saved customize-customized customize-face-other-window customize-face customize-option-other-window customize-variable customize-other-window customize customize-save-variable customize-set-variable customize-set-value) "cus-edit" "lisp/cus-edit.el") + +(autoload 'customize-set-value "cus-edit" "\ +Set VARIABLE to VALUE. VALUE is a Lisp object. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value." t nil) + +(autoload 'customize-set-variable "cus-edit" "\ +Set the default for VARIABLE to VALUE. VALUE is a Lisp object. + +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +The `customized-value' property of the VARIABLE will be set to a list +with a quoted VALUE as its sole list member. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. " t nil) + +(autoload 'customize-save-variable "cus-edit" "\ +Set the default for VARIABLE to VALUE, and save it for future sessions. +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +The `customized-value' property of the VARIABLE will be set to a list +with a quoted VALUE as its sole list member. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. " t nil) + +(autoload 'customize "cus-edit" "\ +Select a customization buffer which you can use to set user options. +User options are structured into \"groups\". +The default group is `Emacs'." t nil) + +(defalias 'customize-group 'customize) + +(autoload 'customize-other-window "cus-edit" "\ +Customize SYMBOL, which must be a customization group." t nil) + +(defalias 'customize-group-other-window 'customize-other-window) + +(defalias 'customize-option 'customize-variable) + +(autoload 'customize-variable "cus-edit" "\ +Customize SYMBOL, which must be a user option variable." t nil) + +(defalias 'customize-variable-other-window 'customize-option-other-window) + +(autoload 'customize-option-other-window "cus-edit" "\ +Customize SYMBOL, which must be a user option variable. +Show the buffer in another window, but don't select it." t nil) + +(autoload 'customize-face "cus-edit" "\ +Customize SYMBOL, which should be a face name or nil. +If SYMBOL is nil, customize all faces." t nil) + +(autoload 'customize-face-other-window "cus-edit" "\ +Show customization buffer for FACE in other window." t nil) + +(autoload 'customize-customized "cus-edit" "\ +Customize all user options set since the last save in this session." t nil) + +(autoload 'customize-saved "cus-edit" "\ +Customize all already saved user options." t nil) + +(autoload 'customize-apropos "cus-edit" "\ +Customize all user options matching REGEXP. +If ALL is `options', include only options. +If ALL is `faces', include only faces. +If ALL is `groups', include only groups. +If ALL is t (interactively, with prefix arg), include options which are not +user-settable, as well as faces and groups." t nil) + +(autoload 'customize-apropos-options "cus-edit" "\ +Customize all user options matching REGEXP. +With prefix arg, include options which are not user-settable." t nil) + +(autoload 'customize-apropos-faces "cus-edit" "\ +Customize all user faces matching REGEXP." t nil) + +(autoload 'customize-apropos-groups "cus-edit" "\ +Customize all user groups matching REGEXP." t nil) + +(autoload 'custom-buffer-create "cus-edit" "\ +Create a buffer containing OPTIONS. +Optional NAME is the name of the buffer. +OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where +SYMBOL is a customization option, and WIDGET is a widget for editing +that option." nil nil) + +(autoload 'custom-buffer-create-other-window "cus-edit" "\ +Create a buffer containing OPTIONS. +Optional NAME is the name of the buffer. +OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where +SYMBOL is a customization option, and WIDGET is a widget for editing +that option." nil nil) + +(autoload 'customize-browse "cus-edit" "\ +Create a tree browser for the customize hierarchy." t nil) + +(defcustom custom-file (if (boundp 'emacs-user-extension-dir) (concat "~" init-file-user emacs-user-extension-dir "options.el") "~/.emacs") "File used for storing customization information.\nIf you change this from the default \"~/.emacs\" you need to\nexplicitly load that file for the settings to take effect." :type 'file :group 'customize) + +(autoload 'customize-save-customized "cus-edit" "\ +Save all user options which have been set in this session." t nil) + +(autoload 'custom-save-all "cus-edit" "\ +Save all customizations in `custom-file'." nil nil) + +(autoload 'custom-menu-create "cus-edit" "\ +Create menu for customization group SYMBOL. +The menu is in a format applicable to `easy-menu-define'." nil nil) + +(autoload 'customize-menu-create "cus-edit" "\ +Return a customize menu for customization group SYMBOL. +If optional NAME is given, use that as the name of the menu. +Otherwise the menu will be named `Customize'. +The format is suitable for use with `easy-menu-define'." nil nil) + +;;;*** + +;;;### (autoloads (custom-set-faces custom-declare-face) "cus-face" "lisp/cus-face.el") + +(autoload 'custom-declare-face "cus-face" "\ +Like `defface', but FACE is evaluated as a normal argument." nil nil) + +(autoload 'custom-set-faces "cus-face" "\ +Initialize faces according to user preferences. +The arguments should be a list where each entry has the form: + + (FACE SPEC [NOW]) + +SPEC will be stored as the saved value for FACE. If NOW is present +and non-nil, FACE will also be created according to SPEC. + +See `defface' for the format of SPEC." nil nil) + +;;;*** + +;;;### (autoloads (disassemble) "disass" "lisp/disass.el") + +(autoload 'disassemble "disass" "\ +Print disassembled code for OBJECT in (optional) BUFFER. +OBJECT can be a symbol defined as a function, or a function itself +\(a lambda expression or a compiled-function object). +If OBJECT is not already compiled, we compile it, but do not +redefine OBJECT if it is a symbol." t nil) + +;;;*** + +;;;### (autoloads (widget-minor-mode widget-browse-other-window widget-browse widget-browse-at) "wid-browse" "lisp/wid-browse.el") + +(autoload 'widget-browse-at "wid-browse" "\ +Browse the widget under point." t nil) + +(autoload 'widget-browse "wid-browse" "\ +Create a widget browser for WIDGET." t nil) + +(autoload 'widget-browse-other-window "wid-browse" "\ +Show widget browser for WIDGET in other window." t nil) + +(autoload 'widget-minor-mode "wid-browse" "\ +Togle minor mode for traversing widgets. +With arg, turn widget mode on if and only if arg is positive." t nil) + +;;;*** + +;;;### (autoloads (widget-delete widget-create widget-prompt-value) "wid-edit" "lisp/wid-edit.el") + +(autoload 'widget-prompt-value "wid-edit" "\ +Prompt for a value matching WIDGET, using PROMPT. +The current value is assumed to be VALUE, unless UNBOUND is non-nil." nil nil) + +(autoload 'widget-create "wid-edit" "\ +Create widget of TYPE. +The optional ARGS are additional keyword arguments." nil nil) + +(autoload 'widget-delete "wid-edit" "\ +Delete WIDGET." nil nil) + +;;;*** + +;;;### (autoloads (font-menu-weight-constructor font-menu-size-constructor font-menu-family-constructor reset-device-font-menus) "x-font-menu" "lisp/x-font-menu.el") + +(defcustom font-menu-ignore-scaled-fonts t "*If non-nil, then the font menu will try to show only bitmap fonts." :type 'boolean :group 'x) + +(defcustom font-menu-this-frame-only-p nil "*If non-nil, then changing the default font from the font menu will only\naffect one frame instead of all frames." :type 'boolean :group 'x) + +(fset 'install-font-menus 'reset-device-font-menus) + +(autoload 'reset-device-font-menus "x-font-menu" "\ +Generates the `Font', `Size', and `Weight' submenus for the Options menu. +This is run the first time that a font-menu is needed for each device. +If you don't like the lazy invocation of this function, you can add it to +`create-device-hook' and that will make the font menus respond more quickly +when they are selected for the first time. If you add fonts to your system, +or if you change your font path, you can call this to re-initialize the menus." nil nil) + +(autoload 'font-menu-family-constructor "x-font-menu" nil nil nil) + +(autoload 'font-menu-size-constructor "x-font-menu" nil nil nil) + +(autoload 'font-menu-weight-constructor "x-font-menu" nil nil nil) + +;;;*** + +(provide 'TopLevel-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/auto-save.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/auto-save.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,547 @@ +;;; auto-save.el -- Safer autosaving for EFS and tmp. + +;; Copyright (C) 1997 Free Software Foundation, Inc. +;; Copyright (C) 1992 by Sebastian Kremer + +;; Author: Sebastian Kremer +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, dumped +;; Version: 1.26 + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 1, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Not in FSF + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; Combines autosaving for efs (to a local or remote directory) +;; with the ability to do autosaves to a fixed directory on a local +;; disk, in case NFS is slow. The auto-save file used for +;; /usr/foo/bar/baz.txt +;; will be +;; AUTOSAVE/#\!usr\!foo\!bar\!baz.txt# +;; assuming AUTOSAVE is the non-nil value of the variable +;; `auto-save-directory'. + +;; Takes care that autosave files for non-file-buffers (e.g. *mail*) +;; from two simultaneous Emacses don't collide. + +;; Autosaves even if the current directory is not writable. + +;; Can limit autosave names to 14 characters using a hash function, +;; see `auto-save-hash-p'. + +;; See `auto-save-directory' and `make-auto-save-file-name' and +;; references therein for complete documentation. + +;; `M-x recover-all-files' will effectively do recover-file on all +;; files whose autosave file is newer (one of the benefits of having +;; all autosave files in the same place). + +;; This file is dumped with XEmacs. + +;; If you want to autosave in the fixed directory /tmp/USER-autosave/ +;; (setq auto-save-directory +;; (concat "/tmp/" (user-login-name) "-autosave/")) + +;; If you don't want to save in /tmp (e.g., because it is swap +;; mounted) but rather in ~/autosave/ +;; (setq auto-save-directory (expand-file-name "~/.autosave/")) + +;; If you want to save each file in its own directory (the default) +;; (setq auto-save-directory nil) +;; You still can take advantage of autosaving efs remote files +;; in a fixed local directory, `auto-save-directory-fallback' will +;; be used. + +;; If you want to use 14 character hashed autosave filenames +;; (setq auto-save-hash-p t) + +;; Finally, put this line after the others in your ~/.emacs: +;; (require 'auto-save) + + +;;; Acknowledgement: + +;; This code is loosely derived from autosave-in-tmp.el by Jamie +;; Zawinski (the version I had was last modified 22 +;; dec 90 jwz) and code submitted to ange-ftp-lovers on Sun, 5 Apr +;; 92 23:20:47 EDT by drw@BOURBAKI.MIT.EDU (Dale R. Worley). +;; auto-save.el tries to cover the functionality of those two +;; packages. + +;; Valuable comments and help from Dale Worley, Andy Norman, Jamie +;; Zawinski and Sandy Rutherford are gratefully acknowledged. + +(defconst auto-save-version "1.26" + "Version number of auto-save.") + +(provide 'auto-save) + + +;;; Customization: + +(defgroup auto-save nil + "Autosaving with support for efs and /tmp." + :group 'data) + +(put 'auto-save-interval 'custom-type 'integer) +(put 'auto-save-interval 'factory-value '(300)) +(custom-add-to-group 'auto-save 'auto-save-interval 'custom-variable) + +(defcustom auto-save-directory nil + + ;; Don't make this user-variable-p, it should be set in .emacs and + ;; left at that. In particular, it should remain constant across + ;; several Emacs session to make recover-all-files work. + + ;; However, it's OK for it to be customizable, as most of the + ;; customizable variables are set at the time `.emacs' is read. + ;; -hniksic + + "If non-nil, fixed directory for autosaving: all autosave files go +there. If this directory does not yet exist at load time, it is +created and its mode is set to 0700 so that nobody else can read your +autosave files. + +If nil, each autosave files goes into the same directory as its +corresponding visited file. + +A non-nil `auto-save-directory' could be on a local disk such as in +/tmp, then auto-saves will always be fast, even if NFS or the +automounter is slow. In the usual case of /tmp being locally mounted, +note that if you run emacs on two different machines, they will not +see each other's auto-save files. + +The value \(expand-file-name \"~/.autosave/\"\) might be better if /tmp +is mounted from swap (possible in SunOS, type `df /tmp' to find out) +and thus vanishes after a reboot, or if your system is particularly +thorough when cleaning up /tmp, clearing even non-empty subdirectories. + +It should never be an efs remote filename because that would +defeat `efs-auto-save-remotely'. + +Unless you set `auto-save-hash-p', you shouldn't set this to a +directory in a filesystem that does not support long filenames, since +a file named + + /home/sk/lib/emacs/lisp/auto-save.el + +will have a longish filename like + + AUTO-SAVE-DIRECTORY/#\\!home\\!sk\\!lib\\!emacs\\!lisp\\!auto-save.el# + +as auto save file. + +See also variables `auto-save-directory-fallback', +`efs-auto-save' and `efs-auto-save-remotely'." + :type '(choice (const :tag "Same as file" nil) + directory) + :group 'auto-save) + + +(defcustom auto-save-hash-p nil + "If non-nil, hashed autosave names of length 14 are used. +This is to avoid autosave filenames longer than 14 characters. +The directory used is `auto-save-hash-directory' regardless of +`auto-save-directory'. +Hashing defeats `recover-all-files', you have to recover files +individually by doing `recover-file'." + :type 'boolean + :group 'auto-save) + +;;; This defvar is in efs.el now, but doesn't hurt to give it here as +;;; well so that loading first auto-save.el does not abort. + +;; #### Now that `auto-save' is dumped, this is looks obnoxious. +(or (boundp 'efs-auto-save) (defvar efs-auto-save 0)) +(or (boundp 'efs-auto-save-remotely) (defvar efs-auto-save-remotely nil)) + +(defcustom auto-save-offer-delete nil + "*If non-nil, `recover-all-files' offers to delete autosave files +that are out of date or were dismissed for recovering. +Special value 'always deletes those files silently." + :type '(choice (const :tag "on" t) + (const :tag "off" nil) + (const :tag "Delete silently" always)) + :group 'auto-save) + +;;;; end of customization + + +;;; Preparations to be done at load time + +(defvar auto-save-directory-fallback (expand-file-name "~/.autosave/") + ;; not user-variable-p, see above + "Directory used for local autosaving of remote files if +both `auto-save-directory' and `efs-auto-save-remotely' are nil. +Also used if a working directory to be used for autosaving is not writable. +This *must* always be the name of directory that exists or can be +created by you, never nil.") + +(defvar auto-save-hash-directory + (expand-file-name "hash/" (or auto-save-directory + auto-save-directory-fallback)) + "If non-nil, directory used for hashed autosave filenames.") + +(defun auto-save-check-directory (var) + (let ((dir (symbol-value var))) + (if (null dir) + nil + ;; Expand and store back into the variable + (set var (setq dir (expand-file-name dir))) + ;; Make sure directory exists + (if (file-directory-p dir) + nil + ;; Else we create and chmod 0700 the directory + (setq dir (directory-file-name dir)) ; some systems need this + (make-directory dir) + (set-file-modes dir #o700))))) + +(mapc #'auto-save-check-directory + '(auto-save-directory auto-save-directory-fallback)) + +(and auto-save-hash-p + (auto-save-check-directory 'auto-save-hash-directory)) + + +;;; Computing an autosave name for a file and vice versa + +;; #### Now that this file is dumped, we should turn off the routine +;; from files.el. But it would make it harder to remove it! + +(defun make-auto-save-file-name (&optional file-name);; redefines files.el + ;; auto-save-file-name-p need not be redefined. + + "Return file name to use for auto-saves of current buffer. +Does not consider `auto-save-visited-file-name'; that is checked +before calling this function. + +Offers to autosave all files in the same `auto-save-directory'. All +autosave files can then be recovered at once with function +`recover-all-files'. + +Takes care to make autosave files for files accessed through efs +be local files if variable `efs-auto-save-remotely' is nil. + +Takes care of slashes in buffer names to prevent autosave errors. + +Takes care that autosave files for buffers not visiting any file (such +as `*mail*') from two simultaneous Emacses don't collide by prepending +the Emacs pid. + +Uses 14 character autosave names if `auto-save-hash-p' is true. + +Autosaves even if the current directory is not writable, using +directory `auto-save-directory-fallback'. + +You can redefine this for customization (he he :-). +See also function `auto-save-file-name-p'." + + ;; We have to be very careful about not signalling an error in this + ;; function since files.el does not provide for this (e.g. find-file + ;; would fail for each new file). + + (setq file-name (or file-name + buffer-file-truename + (and buffer-file-name + (expand-file-name buffer-file-name)))) + (condition-case error-data + (let ( + ;; So autosavename looks like #%...#, roughly as with the + ;; old make-auto-save-file-name function. The + ;; make-temp-name inserts the pid of this Emacs: this + ;; avoids autosaving from two Emacses into the same file. + ;; It cannot be recovered automatically then because in + ;; the next Emacs session (the one after the crash) the + ;; pid will be different, but file-less buffers like + ;; *mail* must be recovered manually anyway. + + ;; jwz: putting the emacs PID in the auto-save file name is bad + ;; news, because that defeats auto-save-recovery of *mail* + ;; buffers -- the (sensible) code in sendmail.el calls + ;; (make-auto-save-file-name) to determine whether there is + ;; unsent, auto-saved mail to recover. If that mail came from a + ;; previous emacs process (far and away the most likely case) + ;; then this can never succeed as the pid differs. + ;;(name-prefix (if file-name nil (make-temp-name "#%"))) + (name-prefix (if file-name nil "#%")) + + (save-name (or file-name + ;; Prevent autosave errors. Buffername + ;; (to become non-dir part of filename) will + ;; be unslashified twice. Don't care. + (auto-save-unslashify-name (buffer-name)))) + (remote-p (and (stringp file-name) + (fboundp 'efs-ftp-path) + (efs-ftp-path file-name)))) + ;; Return the appropriate auto save file name: + (expand-file-name;; a buffername needs this, a filename not + (cond (remote-p + (if efs-auto-save-remotely + (auto-save-name-in-same-directory save-name) + ;; We have to use the `fixed-directory' now since the + ;; `same-directory' would be remote. + ;; It will use the fallback if needed. + (auto-save-name-in-fixed-directory save-name))) + ;; Else it is a local file (or a buffer without a file, + ;; hence the name-prefix). + ((or auto-save-directory auto-save-hash-p) + ;; Hashed files always go into the special hash dir, + ;; never in the same directory, to make recognizing + ;; reliable. + (auto-save-name-in-fixed-directory save-name name-prefix)) + (t + (auto-save-name-in-same-directory save-name name-prefix))))) + + ;; If any error occurs in the above code, return what the old + ;; version of this function would have done. It is not ok to + ;; return nil, e.g., when after-find-file tests + ;; file-newer-than-file-p, nil would bomb. + + (error (warn "Error caught in `make-auto-save-file-name':\n%s" + (error-message-string error-data)) + (if buffer-file-name + (concat (file-name-directory buffer-file-name) + "#" + (file-name-nondirectory buffer-file-name) + "#") + (expand-file-name (concat "#%" (buffer-name) "#")))))) + +(defun auto-save-original-name (savename) + "Reverse of `make-auto-save-file-name'. +Returns nil if SAVENAME was not associated with a file (e.g., it came +from an autosaved `*mail*' buffer) or does not appear to be an +autosave file at all. +Hashed files are not understood, see `auto-save-hash-p'." + (let ((basename (file-name-nondirectory savename)) + (savedir (file-name-directory savename))) + (cond ((or (not (auto-save-file-name-p basename)) + (string-match "^#%" basename)) + nil) + ;; now we know it looks like #...# thus substring is safe to use + ((or (equal savedir auto-save-directory) ; 2nd arg may be nil + (equal savedir auto-save-directory-fallback)) + ;; it is of the `-fixed-directory' type + (auto-save-slashify-name (substring basename 1 -1))) + (t + ;; else it is of `-same-directory' type + (concat savedir (substring basename 1 -1)))))) + +(defun auto-save-name-in-fixed-directory (filename &optional prefix) + ;; Unslashify and enclose the whole FILENAME in `#' to make an auto + ;; save file in the auto-save-directory, or if that is nil, in + ;; auto-save-directory-fallback (which must be the name of an + ;; existing directory). If the results would be too long for 14 + ;; character filenames, and `auto-save-hash-p' is set, hash FILENAME + ;; into a shorter name. + ;; Optional PREFIX is string to use instead of "#" to prefix name. + (let ((base-name (concat (or prefix "#") + (auto-save-unslashify-name filename) + "#"))) + (if (and auto-save-hash-p + auto-save-hash-directory + (> (length base-name) 14)) + (expand-file-name (auto-save-cyclic-hash-14 filename) + auto-save-hash-directory) + (expand-file-name base-name + (or auto-save-directory + auto-save-directory-fallback))))) + +(defun auto-save-name-in-same-directory (filename &optional prefix) + ;; Enclose the non-directory part of FILENAME in `#' to make an auto + ;; save file in the same directory as FILENAME. But if this + ;; directory is not writable, use auto-save-directory-fallback. + ;; FILENAME is assumed to be in non-directory form (no trailing slash). + ;; It may be a name without a directory part (pesumably it really + ;; comes from a buffer name then), the fallback is used then. + ;; Optional PREFIX is string to use instead of "#" to prefix name. + (let ((directory (file-name-directory filename))) + (or (null directory) + (file-writable-p directory) + (setq directory auto-save-directory-fallback)) + (concat directory ; (concat nil) is "" + (or prefix "#") + (file-name-nondirectory filename) + "#"))) + +;; #### The following two should probably use `replace-in-string'. + +(defun auto-save-unslashify-name (s) + ;; "Quote any slashes in string S by replacing them with the two + ;;characters `\\!'. + ;;Also, replace any backslash by double backslash, to make it one-to-one." + (let ((limit 0)) + (while (string-match "[/\\]" s limit) + (setq s (concat (substring s 0 (match-beginning 0)) + (if (string= (substring s + (match-beginning 0) + (match-end 0)) + "/") + "\\!" + "\\\\") + (substring s (match-end 0)))) + (setq limit (1+ (match-end 0))))) + s) + +(defun auto-save-slashify-name (s) + ;;"Reverse of `auto-save-unslashify-name'." + (let (pos) + (while (setq pos (string-match "\\\\[\\!]" s pos)) + (setq s (concat (substring s 0 pos) + (if (eq ?! (aref s (1+ pos))) "/" "\\") + (substring s (+ pos 2))) + pos (1+ pos)))) + s) + + +;;; Hashing for autosave names + +;;; Hashing function contributed by Andy Norman +;;; based upon C code from pot@fly.cnuce.cnr.IT (Francesco Potorti`). + +(defun auto-save-cyclic-hash-14 (s) + ;; "Hash string S into a string of length 14. + ;; A 7-bytes cyclic code for burst correction is calculated on a + ;; byte-by-byte basis. The polynomial used is D^7 + D^6 + D^3 +1. + ;; The resulting string consists of hexadecimal digits [0-9a-f]. + ;; In particular, it contains no slash, so it can be used as autosave name." + (let ((crc (make-string 7 ?\0))) + (mapc + (lambda (new) + (setq new (+ new (aref crc 6))) + (aset crc 6 (+ (aref crc 5) new)) + (aset crc 5 (aref crc 4)) + (aset crc 4 (aref crc 3)) + (aset crc 3 (+ (aref crc 2) new)) + (aset crc 2 (aref crc 1)) + (aset crc 1 (aref crc 0)) + (aset crc 0 new)) + s) + (format "%02x%02x%02x%02x%02x%02x%02x" + (aref crc 0) + (aref crc 1) + (aref crc 2) + (aref crc 3) + (aref crc 4) + (aref crc 5) + (aref crc 6)))) + +;; #### It is unclear to me how the following function is useful. It +;; should be used in `auto-save-name-in-same-directory', if anywhere. +;; -hniksic + +;; This leaves two characters that could be used to wrap it in `#' or +;; make two filenames from it: one for autosaving, and another for a +;; file containing the name of the autosaved filed, to make hashing +;; reversible. +;(defun auto-save-cyclic-hash-12 (s) +; "Outputs the 12-characters ascii hex representation of a 6-bytes +;cyclic code for burst correction calculated on STRING on a +;byte-by-byte basis. The used polynomial is D^6 + D^5 + D^4 + D^3 +1." +; (let ((crc (make-string 6 0))) +; (mapc +; (lambda (new) +; (setq new (+ new (aref crc 5))) +; (aset crc 5 (+ (aref crc 4) new)) +; (aset crc 4 (+ (aref crc 3) new)) +; (aset crc 3 (+ (aref crc 2) new)) +; (aset crc 2 (aref crc 1)) +; (aset crc 1 (aref crc 0)) +; (aset crc 0 new)) +; s) +; (format "%02x%02x%02x%02x%02x%02x" +; (aref crc 0) +; (aref crc 1) +; (aref crc 2) +; (aref crc 3) +; (aref crc 4) +; (aref crc 5)))) + + + +;;; Recovering files + +(defun recover-all-files (&optional silent) + "Do recover-file for all autosave files which are current. +Only works if you have a non-nil `auto-save-directory'. + +Optional prefix argument SILENT means to be silent about non-current +autosave files. This is useful if invoked automatically at Emacs +startup. + +If `auto-save-offer-delete' is t, this function will offer to delete +old or rejected autosave files. + +Hashed files (see `auto-save-hash-p') are not understood, use +`recover-file' to recover them individually." + (interactive "P") + (let ((savefiles (directory-files auto-save-directory + t "\\`#" nil t)) + afile ; the auto save file + file ; its original file + (total 0) ; # of files offered to recover + (count 0)) ; # of files actually recovered + (or (equal auto-save-directory auto-save-directory-fallback) + (setq savefiles + (nconc savefiles + (directory-files auto-save-directory-fallback + t "\\`#" nil t)))) + (while savefiles + (setq afile (car savefiles) + file (auto-save-original-name afile) + savefiles (cdr savefiles)) + (cond ((and file (not (file-newer-than-file-p afile file))) + (warn "Autosave file \"%s\" is not current." afile)) + (t + (incf total) + (with-output-to-temp-buffer "*Directory*" + (apply 'call-process "ls" nil standard-output nil + "-l" afile (if file (list file)))) + (if (yes-or-no-p (format "Recover %s from auto save file? " + (or file "non-file buffer"))) + (let* ((obuf (current-buffer))) + (set-buffer (if file + (find-file-noselect file t) + (generate-new-buffer "*recovered*"))) + (setq buffer-read-only nil) + (erase-buffer) + (insert-file-contents afile nil) + (ignore-errors + (after-find-file nil)) + (setq buffer-auto-save-file-name nil) + (incf count) + (message "\ +Auto-save off in buffer \"%s\" till you do M-x auto-save-mode." + (buffer-name)) + (set-buffer obuf) + (sit-for 1)) + ;; If not used for recovering, offer to delete + ;; autosave file + (and auto-save-offer-delete + (or (eq 'always auto-save-offer-delete) + (yes-or-no-p + (format "Delete autosave file for `%s'? " file))) + (delete-file afile)))))) + (if (zerop total) + (or silent (message "Nothing to recover.")) + (message "%d/%d file%s recovered." count total (if (= count 1) "" "s")))) + (and (get-buffer "*Directory*") + (kill-buffer "*Directory*"))) + +;;; auto-save.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/auto-show.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/auto-show.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,203 @@ +;;; auto-show.el --- perform automatic horizontal scrolling as point moves + +;; Copyright (C) 1997 Free Software Foundation, Inc. +;; This file is in the public domain. + +;; Author: Pete Ware +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Emacs/Mule zeta. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; Modified by: Ben Wing + +;; This file provides functions that +;; automatically scroll the window horizontally when the point moves +;; off the left or right side of the window. + +;; Once this library is loaded, automatic horizontal scrolling +;; occurs whenever long lines are being truncated. +;; To request truncation of long lines, set the variable +;; Setting the variable `truncate-lines' to non-nil. +;; You can do this for all buffers as follows: +;; +;; (set-default 'truncate-lines t) + +;; Here is how to do it for C mode only: +;; +;; (set-default 'truncate-lines nil) ; this is the original value +;; (defun my-c-mode-hook () +;; "Run when C-mode starts up. Changes ..." +;; ... set various personal preferences ... +;; (setq truncate-lines t)) +;; (add-hook 'c-mode-hook 'my-c-mode-hook) +;; +;; +;; As a finer level of control, you can still have truncated lines but +;; without the automatic horizontal scrolling by setting the buffer +;; local variable `auto-show-mode' to nil. The default value is t. +;; The command `auto-show-mode' toggles the value of the variable +;; `auto-show-mode'. + +;;; Code: + +(defgroup auto-show nil + "Perform automatic horizontal scrolling as point moves." + :group 'display + :group 'extensions) + +;; This is preloaded, so we don't need special :set, :require, etc. +(defcustom auto-show-mode t + "*Non-nil enables automatic horizontal scrolling, when lines are truncated. +The default value is t. To change the default, do this: + (set-default 'auto-show-mode nil) +See also command `auto-show-mode'. +This variable has no effect when lines are not being truncated. +This variable is automatically local in each buffer where it is set." + :type 'boolean + :group 'auto-show) + +(make-variable-buffer-local 'auto-show-mode) + +(defcustom auto-show-shift-amount 8 + "*Extra columns to scroll. for automatic horizontal scrolling." + :type 'integer + :group 'auto-show) + +(defcustom auto-show-show-left-margin-threshold 50 + "*Threshold column for automatic horizontal scrolling to the right. +If point is before this column, we try to scroll to make the left margin +visible. Setting this to 0 disables this feature." + :type 'number + :group 'auto-show) + +(defun auto-show-truncationp () + "True if line truncation is enabled for the selected window." + ;; XEmacs change (use specifiers) + ;; ### There should be a more straightforward way to do this from elisp. + (or truncate-lines + (and truncate-partial-width-windows + (< (+ (window-width) + (specifier-instance left-margin-width) + (specifier-instance right-margin-width)) + (frame-width))))) + +(defun auto-show-mode (arg) + "Turn automatic horizontal scroll mode on or off. +With arg, turn auto scrolling on if arg is positive, off otherwise. +This mode is enabled or disabled for each buffer individually. +It takes effect only when `truncate-lines' is non-nil." + (interactive "P") + (setq auto-show-mode + (if (null arg) + (not auto-show-mode) + (> (prefix-numeric-value arg) 0)))) + +;; XEmacs addition: +(defvar auto-show-inhibiting-commands + '(scrollbar-char-left + scrollbar-char-right + scrollbar-page-left + scrollbar-page-right + scrollbar-to-left + scrollbar-to-right + scrollbar-horizontal-drag) + "Commands that inhibit auto-show behavior. +This normally includes the horizontal scrollbar commands.") + +;; XEmacs addition: +(defun auto-show-should-take-action-p () + (and auto-show-mode (auto-show-truncationp) + (equal (window-buffer) (current-buffer)) + (not (memq this-command auto-show-inhibiting-commands)))) + +;; XEmacs addition: +(defun auto-show-make-region-visible (start end) + "Move point in such a way that the region (START, END) is visible. +This only does anything if auto-show-mode is enabled, and it doesn't +actually do any horizontal scrolling; rather, it just sets things up so +that the region will be visible when `auto-show-make-point-visible' +is next called (this happens after every command)." + (if (auto-show-should-take-action-p) + (let* ((col (current-column)) ;column on line point is at + (scroll (window-hscroll));how far window is scrolled + (w-width (- (window-width) + (if (> scroll 0) + 2 1))) ;how wide window is on the screen + (right-col (+ scroll w-width)) + (start-col (save-excursion (goto-char start) (current-column))) + (end-col (save-excursion (goto-char end) (current-column)))) + (cond ((and (>= start-col scroll) + (<= end-col right-col)) + ;; already completely visible + nil) + ((< start-col scroll) + (scroll-right (- scroll start-col))) + (t + (scroll-left (- end-col right-col))))))) + +(defun auto-show-make-point-visible (&optional ignore-arg) + "Scroll horizontally to make point visible, if that is enabled. +This function only does something if `auto-show-mode' is non-nil +and longlines are being truncated in the selected window. +See also the command `auto-show-mode'." + (interactive) + ;; XEmacs change + (if (auto-show-should-take-action-p) + (let* ((col (current-column)) ;column on line point is at + (scroll (window-hscroll)) ;how far window is scrolled + (w-width (- (window-width) + (if (> scroll 0) + 2 1))) ;how wide window is on the screen + (right-col (+ scroll w-width))) + (if (and (< col auto-show-show-left-margin-threshold) + (< col (window-width)) + (> scroll 0)) + (scroll-right scroll) + (if (< col scroll) ;to the left of the screen + (scroll-right (+ (- scroll col) auto-show-shift-amount)) + (if (or (> col right-col) ;to the right of the screen + (and (= col right-col) + (not (eolp)))) + (scroll-left (+ auto-show-shift-amount + (- col (+ scroll w-width)))))))))) + +;; XEmacs change: +;; #### instead of this, we kludgily call it from the C code, to make sure +;; that it's done after any other things on post-command-hook (which might +;; move point). +;; Do auto-scrolling after commands. +;;(add-hook 'post-command-hook 'auto-show-make-point-visible) + +;; If being dumped, turn it on right away. +(when (boundp 'load-gc) + (auto-show-mode 1)) + +;; Do auto-scrolling in comint buffers after process output also. +; XEmacs -- don't do this now, it messes up comint. +;(add-hook 'comint-output-filter-functions 'auto-show-make-point-visible t) + +(provide 'auto-show) + +;;; auto-show.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/backquote.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/backquote.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,304 @@ +;;; backquote.el --- Full backquote support for elisp. Reverse compatible too. + +;; Copyright (C) 1997 Free Software Foundation, Inc. + +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Not synched with FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; The bulk of the code is originally from CMU Common Lisp (original notice +;; below). + +;; It correctly supports nested backquotes and backquoted vectors. + +;; Converted to work with elisp by Miles Bader + +;; Changes by Jonathan Stigelman : +;; - Documentation added +;; - support for old-backquote-compatibility-hook nixed because the +;; old-backquote compatibility is now done in the reader... +;; - nixed support for |,.| because +;; (a) it's not in CLtl2 +;; (b) ",.foo" is the same as ". ,foo" +;; (c) because RMS isn't interested in using this version of backquote.el +;; +;; wing@666.com; added ,. support back in: +;; (a) yes, it is in CLtl2. Read closely on page 529. +;; (b) RMS in 19.30 adds C support for ,. even if it's not really +;; handled. +;; +;; ********************************************************************** +;; This code was written as part of the CMU Common Lisp project at +;; Carnegie Mellon University, and has been placed in the public domain. +;; If you want to use this code or any part of CMU Common Lisp, please contact +;; Scott Fahlman or slisp-group@cs.cmu.edu. +;; +;; ********************************************************************** +;; +;; BACKQUOTE: Code Spice Lispified by Lee Schumacher. +;; +;; The flags passed back by BQ-PROCESS-2 can be interpreted as follows: +;; +;; |`,|: [a] => a +;; NIL: [a] => a ;the NIL flag is used only when a is NIL +;; T: [a] => a ;the T flag is used when a is self-evaluating +;; QUOTE: [a] => (QUOTE a) +;; APPEND: [a] => (APPEND . a) +;; NCONC: [a] => (NCONC . a) +;; LIST: [a] => (LIST . a) +;; LIST*: [a] => (LIST* . a) +;; +;; The flags are combined according to the following set of rules: +;; ([a] means that a should be converted according to the previous table) +;; +;; \ car || otherwise | QUOTE or | |`,@| | |`,.| +;;cdr \ || | T or NIL | | +;;============================================================================ +;; |`,| ||LIST* ([a] [d]) |LIST* ([a] [d]) |APPEND (a [d]) |NCONC (a [d]) +;; NIL ||LIST ([a]) |QUOTE (a) | a | a +;;QUOTE or T||LIST* ([a] [d]) |QUOTE (a . d) |APPEND (a [d]) |NCONC (a [d]) +;; APPEND ||LIST* ([a] [d]) |LIST* ([a] [d]) |APPEND (a . d) |NCONC (a [d]) +;; NCONC ||LIST* ([a] [d]) |LIST* ([a] [d]) |APPEND (a [d]) |NCONC (a . d) +;; LIST ||LIST ([a] . d) |LIST ([a] . d) |APPEND (a [d]) |NCONC (a [d]) +;; LIST* ||LIST* ([a] . d) |LIST* ([a] . d) |APPEND (a [d]) |NCONC (a [d]) +;; +;; involves starting over again pretending you had read ".,a)" instead +;; of ",@a)" +;; + +;; These are the forms it expects: |backquote| |`| |,| |,@| and |,.|. + +;;; Code: + +(defconst bq-backquote-marker 'backquote) +(defconst bq-backtick-marker '\`) ; remnant of the old lossage +(defconst bq-comma-marker '\,) +(defconst bq-at-marker '\,@) +(defconst bq-dot-marker '\,\.) + +;;; ---------------------------------------------------------------- + +(fset '\` 'backquote) + +(defmacro backquote (template) + "Expand the internal representation of a backquoted TEMPLATE into a lisp form. + +The backquote character is like the quote character in that it prevents the +template which follows it from being evaluated, except that backquote +permits you to evaluate portions of the quoted template. A comma character +inside TEMPLATE indicates that the following item should be evaluated. A +comma character may be followed by an at-sign, which indicates that the form +which follows should be evaluated and inserted and \"spliced\" into the +template. Forms following ,@ must evaluate to lists. + +Here is how to use backquotes: + (setq p 'b + q '(c d e)) + `(a ,p ,@q) -> (a b c d e) + `(a . b) -> (a . b) + `(a . ,p) -> (a . b) + +The XEmacs lisp reader expands lisp backquotes as it reads them. +Examples: + `atom is read as (backquote atom) + `(a ,b ,@(c d e)) is read as (backquote (a (\\, b) (\\,\\@ (c d e)))) + `(a . ,p) is read as (backquote (a \\, p)) + +\(backquote TEMPLATE) is a macro that produces code to construct TEMPLATE. +Note that this is very slow in interpreted code, but fast if you compile. +TEMPLATE is one or more nested lists or vectors, which are `almost quoted'. +They are copied recursively, with elements preceded by comma evaluated. + (backquote (a b)) == (list 'a 'b) + (backquote (a [b c])) == (list 'a (vector 'b 'c)) + +However, certain special lists are not copied. They specify substitution. +Lists that look like (\\, EXP) are evaluated and the result is substituted. + (backquote (a (\\, (+ x 5)))) == (list 'a (+ x 5)) + +Elements of the form (\\,\\@ EXP) are evaluated and then all the elements +of the result are substituted. This result must be a list; it may +be `nil'. + +Elements of the form (\\,\\. EXP) are evaluated and then all the elements +of the result are concatenated to the list of preceding elements in the list. +They must occur as the last element of a list (not a vector). +EXP may evaluate to nil. + +As an example, a simple macro `push' could be written: + (defmacro push (v l) + `(setq ,l (cons ,@(list v l)))) +or as + (defmacro push (v l) + `(setq ,l (cons ,v ,l))) + +For backwards compatibility, old-style emacs-lisp backquotes are still read. + OLD STYLE NEW STYLE + (` (foo (, bar) (,@ bing))) `(foo ,bar ,@bing) + +Because of the old-style backquote support, you cannot use a new-style +backquoted form as the first element of a list. Perhaps some day this +restriction will go away, but for now you should be wary of it: + (`(this ,will ,@fail)) + ((` (but (, this) will (,@ work)))) +This is an extremely rare thing to need to do in lisp." + (bq-process template)) + +;;; ---------------------------------------------------------------- + +(defconst bq-comma-flag 'unquote) +(defconst bq-at-flag 'unquote-splicing) +(defconst bq-dot-flag 'unquote-nconc-splicing) + +(defun bq-process (form) + (let* ((flag-result (bq-process-2 form)) + (flag (car flag-result)) + (result (cdr flag-result))) + (cond ((eq flag bq-at-flag) + (error ",@ after ` in form: %s" form)) + ((eq flag bq-dot-flag) + (error ",. after ` in form: %s" form)) + (t + (bq-process-1 flag result))))) + +;;; ---------------------------------------------------------------- + +(defun bq-vector-contents (vec) + (let ((contents nil) + (n (length vec))) + (while (> n 0) + (setq n (1- n)) + (setq contents (cons (aref vec n) contents))) + contents)) + +;;; This does the expansion from table 2. +(defun bq-process-2 (code) + (cond ((vectorp code) + (let* ((dflag-d + (bq-process-2 (bq-vector-contents code)))) + (cons 'vector (bq-process-1 (car dflag-d) (cdr dflag-d))))) + ((atom code) + (cond ((null code) (cons nil nil)) + ((or (numberp code) (eq code t)) + (cons t code)) + (t (cons 'quote code)))) + ((eq (car code) bq-at-marker) + (cons bq-at-flag (nth 1 code))) + ((eq (car code) bq-dot-marker) + (cons bq-dot-flag (nth 1 code))) + ((eq (car code) bq-comma-marker) + (bq-comma (nth 1 code))) + ((or (eq (car code) bq-backquote-marker) + (eq (car code) bq-backtick-marker)) ; old lossage + (bq-process-2 (bq-process (nth 1 code)))) + (t (let* ((aflag-a (bq-process-2 (car code))) + (aflag (car aflag-a)) + (a (cdr aflag-a))) + (let* ((dflag-d (bq-process-2 (cdr code))) + (dflag (car dflag-d)) + (d (cdr dflag-d))) + (if (eq dflag bq-at-flag) + ;; get the errors later. + (error ",@ after dot in %s" code)) + (if (eq dflag bq-dot-flag) + (error ",. after dot in %s" code)) + (cond + ((eq aflag bq-at-flag) + (if (null dflag) + (bq-comma a) + (cons 'append + (cond ((eq dflag 'append) + (cons a d )) + (t (list a (bq-process-1 dflag d))))))) + ((eq aflag bq-dot-flag) + (if (null dflag) + (bq-comma a) + (cons 'nconc + (cond ((eq dflag 'nconc) + (cons a d)) + (t (list a (bq-process-1 dflag d))))))) + ((null dflag) + (if (memq aflag '(quote t nil)) + (cons 'quote (list a)) + (cons 'list (list (bq-process-1 aflag a))))) + ((memq dflag '(quote t)) + (if (memq aflag '(quote t nil)) + (cons 'quote (cons a d )) + (cons 'list* (list (bq-process-1 aflag a) + (bq-process-1 dflag d))))) + (t (setq a (bq-process-1 aflag a)) + (if (memq dflag '(list list*)) + (cons dflag (cons a d)) + (cons 'list* + (list a (bq-process-1 dflag d))))))))))) + +;;; This handles the cases +(defun bq-comma (code) + (cond ((atom code) + (cond ((null code) + (cons nil nil)) + ((or (numberp code) (eq code 't)) + (cons t code)) + (t (cons bq-comma-flag code)))) + ((eq (car code) 'quote) + (cons (car code) (car (cdr code)))) + ((memq (car code) '(append list list* nconc)) + (cons (car code) (cdr code))) + ((eq (car code) 'cons) + (cons 'list* (cdr code))) + (t (cons bq-comma-flag code)))) + +;;; This handles table 1. +(defun bq-process-1 (flag thing) + (cond ((or (eq flag bq-comma-flag) + (memq flag '(t nil))) + thing) + ((eq flag 'quote) + (list 'quote thing)) + ((eq flag 'vector) + (list 'apply '(function vector) thing)) + (t (cons (cdr + (assq flag + '((cons . cons) + (list* . bq-list*) + (list . list) + (append . append) + (nconc . nconc)))) + thing)))) + +;;; ---------------------------------------------------------------- + +(defmacro bq-list* (&rest args) + "Returns a list of its arguments with last cons a dotted pair." + (setq args (reverse args)) + (let ((result (car args))) + (setq args (cdr args)) + (while args + (setq result (list 'cons (car args) result)) + (setq args (cdr args))) + result)) + +(provide 'backquote) + +;;; backquote.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/buff-menu.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/buff-menu.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,639 @@ +;;; buff-menu.el --- buffer menu main function and support functions. + +;; Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. + +;; Maintainer: FSF +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34 except as noted. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; Edit, delete, or change attributes of all currently active Emacs +;; buffers from a list summarizing their state. A good way to browse +;; any special or scratch buffers you have loaded, since you can't find +;; them by filename. The single entry point is `Buffer-menu-mode', +;; normally bound to C-x C-b. + +;;; Change Log: + +;; Merged by esr with recent mods to Emacs 19 buff-menu, 23 Mar 1993 +;; +;; Modified by Bob Weiner, Motorola, Inc., 4/14/89 +;; +;; Added optional backup argument to 'Buffer-menu-unmark' to make it undelete +;; current entry and then move to previous one. +;; +;; Based on FSF code dating back to 1985. + +;;; Code: + +;;;Trying to preserve the old window configuration works well in +;;;simple scenarios, when you enter the buffer menu, use it, and exit it. +;;;But it does strange things when you switch back to the buffer list buffer +;;;with C-x b, later on, when the window configuration is different. +;;;The choice seems to be, either restore the window configuration +;;;in all cases, or in no cases. +;;;I decided it was better not to restore the window config at all. -- rms. + +;;;But since then, I changed buffer-menu to use the selected window, +;;;so q now once again goes back to the previous window configuration. + +;;;(defvar Buffer-menu-window-config nil +;;; "Window configuration saved from entry to `buffer-menu'.") + +; Put buffer *Buffer List* into proper mode right away +; so that from now on even list-buffers is enough to get a buffer menu. + +(defvar Buffer-menu-buffer-column 4) + +(defvar Buffer-menu-mode-map nil "") + +(if Buffer-menu-mode-map + () + (setq Buffer-menu-mode-map (make-keymap)) + (suppress-keymap Buffer-menu-mode-map t) + (set-keymap-name Buffer-menu-mode-map 'Buffer-menu-mode-map) ; XEmacs + (define-key Buffer-menu-mode-map "q" 'Buffer-menu-quit) + (define-key Buffer-menu-mode-map "v" 'Buffer-menu-select) + (define-key Buffer-menu-mode-map "2" 'Buffer-menu-2-window) + (define-key Buffer-menu-mode-map "1" 'Buffer-menu-1-window) + (define-key Buffer-menu-mode-map "f" 'Buffer-menu-this-window) + (define-key Buffer-menu-mode-map "\C-m" 'Buffer-menu-this-window) + (define-key Buffer-menu-mode-map "o" 'Buffer-menu-other-window) + (define-key Buffer-menu-mode-map "\C-o" 'Buffer-menu-switch-other-window) + (define-key Buffer-menu-mode-map "s" 'Buffer-menu-save) + (define-key Buffer-menu-mode-map "d" 'Buffer-menu-delete) + (define-key Buffer-menu-mode-map "k" 'Buffer-menu-delete) + (define-key Buffer-menu-mode-map "\C-d" 'Buffer-menu-delete-backwards) + (define-key Buffer-menu-mode-map "\C-k" 'Buffer-menu-delete) + (define-key Buffer-menu-mode-map "x" 'Buffer-menu-execute) + (define-key Buffer-menu-mode-map " " 'next-line) + (define-key Buffer-menu-mode-map "n" 'next-line) + (define-key Buffer-menu-mode-map "p" 'previous-line) + (define-key Buffer-menu-mode-map 'backspace 'Buffer-menu-backup-unmark) + (define-key Buffer-menu-mode-map 'delete 'Buffer-menu-backup-unmark) + (define-key Buffer-menu-mode-map "~" 'Buffer-menu-not-modified) + (define-key Buffer-menu-mode-map "?" 'describe-mode) + (define-key Buffer-menu-mode-map "u" 'Buffer-menu-unmark) + (define-key Buffer-menu-mode-map "m" 'Buffer-menu-mark) + (define-key Buffer-menu-mode-map "t" 'Buffer-menu-visit-tags-table) + (define-key Buffer-menu-mode-map "%" 'Buffer-menu-toggle-read-only) + (define-key Buffer-menu-mode-map "g" 'revert-buffer) + (define-key Buffer-menu-mode-map 'button2 'Buffer-menu-mouse-select) + (define-key Buffer-menu-mode-map 'button3 'Buffer-menu-popup-menu) + ) + +;; Buffer Menu mode is suitable only for specially formatted data. +(put 'Buffer-menu-mode 'mode-class 'special) + +(defun Buffer-menu-mode () + "Major mode for editing a list of buffers. +Each line describes one of the buffers in Emacs. +Letters do not insert themselves; instead, they are commands. +\\ +\\[Buffer-menu-mouse-select] -- select buffer you click on, in place of the buffer menu. +\\[Buffer-menu-this-window] -- select current line's buffer in place of the buffer menu. +\\[Buffer-menu-other-window] -- select that buffer in another window, + so the buffer menu buffer remains visible in its window. +\\[Buffer-menu-switch-other-window] -- make another window display that buffer. +\\[Buffer-menu-mark] -- mark current line's buffer to be displayed. +\\[Buffer-menu-select] -- select current line's buffer. + Also show buffers marked with m, in other windows. +\\[Buffer-menu-1-window] -- select that buffer in full-frame window. +\\[Buffer-menu-2-window] -- select that buffer in one window, + together with buffer selected before this one in another window. +\\[Buffer-menu-visit-tags-table] -- visit-tags-table this buffer. +\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer. +\\[Buffer-menu-save] -- mark that buffer to be saved, and move down. +\\[Buffer-menu-delete] -- mark that buffer to be deleted, and move down. +\\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted, and move up. +\\[Buffer-menu-execute] -- delete or save marked buffers. +\\[Buffer-menu-unmark] -- remove all kinds of marks from current line. + With prefix argument, also move up one line. +\\[Buffer-menu-backup-unmark] -- back up a line and remove marks. +\\[Buffer-menu-toggle-read-only] -- toggle read-only status of buffer on this line." + (kill-all-local-variables) + (use-local-map Buffer-menu-mode-map) + (setq major-mode 'Buffer-menu-mode) + (setq mode-name "Buffer Menu") + (make-local-variable 'revert-buffer-function) + (setq revert-buffer-function 'Buffer-menu-revert-function) + (setq truncate-lines t) + (setq buffer-read-only t) + (make-local-variable 'mouse-track-click-hook) ; XEmacs + (add-hook 'mouse-track-click-hook 'Buffer-menu-maybe-mouse-select) ; XEmacs + (run-hooks 'buffer-menu-mode-hook)) + +(defun Buffer-menu-revert-function (ignore1 ignore2) + (list-buffers)) + +(defun Buffer-menu-buffer (error-if-non-existent-p) + "Return buffer described by this line of buffer menu." + (let* ((where (save-excursion + (beginning-of-line) + (+ (point) Buffer-menu-buffer-column))) + (name (and (not (eobp)) (get-text-property where 'buffer-name)))) + (if name + (or (get-buffer name) + (if error-if-non-existent-p + (error "No buffer named `%s'" name) + nil)) + (if error-if-non-existent-p + (error "No buffer on this line") + nil)))) + +(defun buffer-menu (&optional arg) + "Make a menu of buffers so you can save, delete or select them. +With argument, show only buffers that are visiting files. +Type ? after invocation to get help on commands available. +Type q immediately to make the buffer menu go away." + (interactive "P") +;;; (setq Buffer-menu-window-config (current-window-configuration)) + (switch-to-buffer (list-buffers-noselect arg)) + (message + "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help.")) + +(defun buffer-menu-other-window (&optional arg) + "Display a list of buffers in another window. +With the buffer list buffer, you can save, delete or select the buffers. +With argument, show only buffers that are visiting files. +Type ? after invocation to get help on commands available. +Type q immediately to make the buffer menu go away." + (interactive "P") +;;; (setq Buffer-menu-window-config (current-window-configuration)) + (switch-to-buffer-other-window (list-buffers-noselect arg)) + (message + "Commands: d, s, x, u; f, o, 1, 2, m, v; ~, %%; q to quit; ? for help.")) + +(defun Buffer-menu-quit () + "Quit the buffer menu." + (interactive) + (let ((buffer (current-buffer))) + ;; Switch away from the buffer menu and bury it. + (switch-to-buffer (other-buffer)) + (bury-buffer buffer))) + +(defun Buffer-menu-mark () + "Mark buffer on this line for being displayed by \\\\[Buffer-menu-select] command." + (interactive) + (beginning-of-line) + (if (looking-at " [-M]") + (ding) + (let ((buffer-read-only nil)) + (delete-char 1) + (insert ?>) + (forward-line 1)))) + +(defun Buffer-menu-unmark (&optional backup) + "Cancel all requested operations on buffer on this line and move down. +Optional ARG means move up." + (interactive "P") + (beginning-of-line) + (if (looking-at " [-M]") + (ding) + (let* ((buf (Buffer-menu-buffer t)) + (mod (buffer-modified-p buf)) + (readonly (save-excursion (set-buffer buf) buffer-read-only)) + (buffer-read-only nil)) + (delete-char 3) + (insert (if readonly (if mod " *%" " %") (if mod " * " " "))))) + (forward-line (if backup -1 1))) + +(defun Buffer-menu-backup-unmark () + "Move up and cancel all requested operations on buffer on line above." + (interactive) + (forward-line -1) + (Buffer-menu-unmark) + (forward-line -1)) + +(defun Buffer-menu-delete (&optional arg) + "Mark buffer on this line to be deleted by \\\\[Buffer-menu-execute] command. +Prefix arg is how many buffers to delete. +Negative arg means delete backwards." + (interactive "p") + (beginning-of-line) + (if (looking-at " [-M]") ;header lines + (ding) + (let ((buffer-read-only nil)) + (if (or (null arg) (= arg 0)) + (setq arg 1)) + (while (> arg 0) + (delete-char 1) + (insert ?D) + (forward-line 1) + (setq arg (1- arg))) + (while (< arg 0) + (delete-char 1) + (insert ?D) + (forward-line -1) + (setq arg (1+ arg)))))) + +(defun Buffer-menu-delete-backwards (&optional arg) + "Mark buffer on this line to be deleted by \\\\[Buffer-menu-execute] command +and then move up one line. Prefix arg means move that many lines." + (interactive "p") + (Buffer-menu-delete (- (or arg 1))) + (while (looking-at " [-M]") + (forward-line 1))) + +(defun Buffer-menu-save () + "Mark buffer on this line to be saved by \\\\[Buffer-menu-execute] command." + (interactive) + (beginning-of-line) + (if (looking-at " [-M]") ;header lines + (ding) + (let ((buffer-read-only nil)) + (forward-char 1) + (delete-char 1) + (insert ?S) + (forward-line 1)))) + +(defun Buffer-menu-not-modified (&optional arg) + "Mark buffer on this line as unmodified (no changes to save)." + (interactive "P") + (save-excursion + (set-buffer (Buffer-menu-buffer t)) + (set-buffer-modified-p arg)) + (save-excursion + (beginning-of-line) + (forward-char 1) + (if (= (char-after (point)) (if arg ? ?*)) + (let ((buffer-read-only nil)) + (delete-char 1) + (insert (if arg ?* ? )))))) + +(defun Buffer-menu-execute () + "Save and/or delete buffers marked with \\\\[Buffer-menu-save] or \\\\[Buffer-menu-delete] commands." + (interactive) + (save-excursion + (goto-char (point-min)) + (forward-line 1) + (while (re-search-forward "^.S" nil t) + (let ((modp nil)) + (save-excursion + (set-buffer (Buffer-menu-buffer t)) + (save-buffer) + (setq modp (buffer-modified-p))) + (let ((buffer-read-only nil)) + (delete-char -1) + (insert (if modp ?* ? )))))) + (save-excursion + (goto-char (point-min)) + (forward-line 1) + (let ((buff-menu-buffer (current-buffer)) + (buffer-read-only nil)) + (while (search-forward "\nD" nil t) + (forward-char -1) + (let ((buf (Buffer-menu-buffer nil))) + (or (eq buf nil) + (eq buf buff-menu-buffer) + (save-excursion (kill-buffer buf)))) + (if (Buffer-menu-buffer nil) + (progn (delete-char 1) + (insert ? )) + (delete-region (point) (progn (forward-line 1) (point))) + (forward-char -1)))))) + +(defun Buffer-menu-select () + "Select this line's buffer; also display buffers marked with `>'. +You can mark buffers with the \\\\[Buffer-menu-mark] command. +This command deletes and replaces all the previously existing windows +in the selected frame." + (interactive) + (let ((buff (Buffer-menu-buffer t)) + (menu (current-buffer)) + (others ()) + tem) + (goto-char (point-min)) + (while (search-forward "\n>" nil t) + (setq tem (Buffer-menu-buffer t)) + (let ((buffer-read-only nil)) + (delete-char -1) + (insert ?\ )) + (or (eq tem buff) (memq tem others) (setq others (cons tem others)))) + (setq others (nreverse others) + tem (/ (1- (frame-height)) (1+ (length others)))) + (delete-other-windows) + (switch-to-buffer buff) + (or (eq menu buff) + (bury-buffer menu)) + (if (equal (length others) 0) + (progn +;;; ;; Restore previous window configuration before displaying +;;; ;; selected buffers. +;;; (if Buffer-menu-window-config +;;; (progn +;;; (set-window-configuration Buffer-menu-window-config) +;;; (setq Buffer-menu-window-config nil))) + (switch-to-buffer buff)) + (while others + (split-window nil tem) + (other-window 1) + (switch-to-buffer (car others)) + (setq others (cdr others))) + (other-window 1) ;back to the beginning! +))) + + + +(defun Buffer-menu-visit-tags-table () + "Visit the tags table in the buffer on this line. See `visit-tags-table'." + (interactive) + (let ((file (buffer-file-name (Buffer-menu-buffer t)))) + (if file + (visit-tags-table file) + (error "Specified buffer has no file")))) + +(defun Buffer-menu-1-window () + "Select this line's buffer, alone, in full frame." + (interactive) + (switch-to-buffer (Buffer-menu-buffer t)) + (bury-buffer (other-buffer)) + (delete-other-windows) + ;; XEmacs: + ;; This is to get w->force_start set to nil. Don't ask me, I only work here. + (set-window-buffer (selected-window) (current-buffer))) + +(defun Buffer-menu-mouse-select (event) + "Select the buffer whose line you click on." + (interactive "e") + (let (buffer) + (save-excursion + (set-buffer (event-buffer event)) ; XEmacs + (save-excursion + (goto-char (event-point event)) ; XEmacs + (setq buffer (Buffer-menu-buffer t)))) + (select-window (event-window event)) ; XEmacs + (if (and (window-dedicated-p (selected-window)) + (eq (selected-window) (frame-root-window))) + (switch-to-buffer-other-frame buffer) + (switch-to-buffer buffer)))) + +;; XEmacs +(defun Buffer-menu-maybe-mouse-select (event &optional click-count) + (interactive "e") + (and (>= click-count 2) + (let ((buffer (current-buffer)) + (point (point)) + (config (current-window-configuration))) + (condition-case nil + (progn + (Buffer-menu-mouse-select event) + t) + (error + (set-window-configuration config) + (set-buffer buffer) + (goto-char point) + nil))))) + +(defun Buffer-menu-this-window () + "Select this line's buffer in this window." + (interactive) + (switch-to-buffer (Buffer-menu-buffer t))) + +(defun Buffer-menu-other-window () + "Select this line's buffer in other window, leaving buffer menu visible." + (interactive) + (switch-to-buffer-other-window (Buffer-menu-buffer t))) + +(defun Buffer-menu-switch-other-window () + "Make the other window select this line's buffer. +The current window remains selected." + (interactive) + (display-buffer (Buffer-menu-buffer t))) + +(defun Buffer-menu-2-window () + "Select this line's buffer, with previous buffer in second window." + (interactive) + (let ((buff (Buffer-menu-buffer t)) + (menu (current-buffer)) + (pop-up-windows t)) + (delete-other-windows) + (switch-to-buffer (other-buffer)) + (pop-to-buffer buff) + (bury-buffer menu))) + +(defun Buffer-menu-toggle-read-only () + "Toggle read-only status of buffer on this line, perhaps via version control." + (interactive) + (let (char) + (save-excursion + (set-buffer (Buffer-menu-buffer t)) + (vc-toggle-read-only) + (setq char (if buffer-read-only ?% ? ))) + (save-excursion + (beginning-of-line) + (forward-char 2) + (if (/= (following-char) char) + (let (buffer-read-only) + (delete-char 1) + (insert char)))))) + +;; XEmacs +(defvar Buffer-menu-popup-menu + '("Buffer Commands" + ["Select Buffer" Buffer-menu-select t] + ["Select buffer Other Window" Buffer-menu-other-window t] + ["Clear Buffer Modification Flag" Buffer-menu-not-modified t] + "----" + ["Mark Buffer for Selection" Buffer-menu-mark t] + ["Mark Buffer for Save" Buffer-menu-save t] + ["Mark Buffer for Deletion" Buffer-menu-delete t] + ["Unmark Buffer" Buffer-menu-unmark t] + "----" + ["Delete/Save Marked Buffers" Buffer-menu-execute t] + )) + +;; XEmacs +(defun Buffer-menu-popup-menu (event) + (interactive "e") + (mouse-set-point event) + (beginning-of-line) + (let ((buffer (Buffer-menu-buffer nil))) + (if buffer + (popup-menu + (nconc (list (car Buffer-menu-popup-menu) + (concat + "Commands on buffer \"" (buffer-name buffer) "\":") + "----") + (cdr Buffer-menu-popup-menu))) + (error "no buffer on this line")))) + + +;; XEmacs +(defvar list-buffers-header-line + (purecopy (concat " MR Buffer Size Mode File\n" + " -- ------ ---- ---- ----\n"))) + +;; XEmacs +(defvar list-buffers-identification 'default-list-buffers-identification + "String used to identify this buffer, or a function of one argument +to generate such a string. This variable is always buffer-local.") +(make-variable-buffer-local 'list-buffers-identification) + +;; XEmacs +;;;###autoload +(defvar list-buffers-directory nil) + +;;;###autoload +(make-variable-buffer-local 'list-buffers-directory) + +;; #### not synched +(defun default-list-buffers-identification (output) + (save-excursion + (let ((file (or (buffer-file-name (current-buffer)) + (and (boundp 'list-buffers-directory) + list-buffers-directory))) + (size (buffer-size)) + (mode mode-name) + eob p s col) + (set-buffer output) + (end-of-line) + (setq eob (point)) + (prin1 size output) + (setq p (point)) + ;; right-justify the size + (move-to-column 19 t) + (setq col (point)) + (if (> eob col) + (goto-char eob)) + (setq s (- 6 (- p col))) + (while (> s 0) ; speed/consing tradeoff... + (insert ? ) + (setq s (1- s))) + (end-of-line) + (indent-to 27 1) + (insert mode) + (if (not file) + nil + ;; if the mode-name is really long, clip it for the filename + (if (> 0 (setq s (- 39 (current-column)))) + (delete-char (max s (- eob (point))))) + (indent-to 40 1) + (insert file))))) + +;; #### not synched +(defun list-buffers-internal (output &optional predicate) + (let ((current (current-buffer)) + (buffers (buffer-list))) + (save-excursion + (set-buffer output) + (setq buffer-read-only nil) + (erase-buffer) + (buffer-disable-undo output) + (insert list-buffers-header-line) + + (while buffers + (let* ((col1 19) + (buffer (car buffers)) + (name (buffer-name buffer)) + this-buffer-line-start) + (setq buffers (cdr buffers)) + (cond ((null name)) ;deleted buffer + ((and predicate + (not (if (stringp predicate) + (string-match predicate name) + (funcall predicate buffer)))) + nil) + (t + (set-buffer buffer) + (let ((ro buffer-read-only) + (id list-buffers-identification)) + (set-buffer output) + (setq this-buffer-line-start (point)) + (insert (if (eq buffer current) + (progn (setq current (point)) ?\.) + ?\ )) + (insert (if (buffer-modified-p buffer) + ?\* + ?\ )) + (insert (if ro + ?\% + ?\ )) + (if (string-match "[\n\"\\ \t]" name) + (let ((print-escape-newlines t)) + (prin1 name output)) + (insert ?\ name)) + (indent-to col1 1) + (cond ((stringp id) + (insert id)) + (id + (set-buffer buffer) + (condition-case e + (funcall id output) + (error + (princ "***" output) (prin1 e output))) + (set-buffer output) + (goto-char (point-max))))) + (put-nonduplicable-text-property this-buffer-line-start + (point) + 'buffer-name name) + (put-nonduplicable-text-property this-buffer-line-start + (point) + 'highlight t) + (insert ?\n))))) + + (Buffer-menu-mode) + (if (not (bufferp current)) + (goto-char current))))) +;(define-key ctl-x-map "\C-b" 'list-buffers) + +(defun list-buffers (&optional files-only) + "Display a list of names of existing buffers. +The list is displayed in a buffer named `*Buffer List*'. +Note that buffers with names starting with spaces are omitted. +Non-null optional arg FILES-ONLY means mention only file buffers. + +The M column contains a * for buffers that are modified. +The R column contains a % for buffers that are read-only." + (interactive (list (if current-prefix-arg t nil))) ; XEmacs + (display-buffer (list-buffers-noselect files-only))) + +;; #### not synched +(defun list-buffers-noselect (&optional files-only) + "Create and return a buffer with a list of names of existing buffers. +The buffer is named `*Buffer List*'. +Note that buffers with names starting with spaces are omitted. +Non-null optional arg FILES-ONLY means mention only file buffers. + +The M column contains a * for buffers that are modified. +The R column contains a % for buffers that are read-only." + (let ((buffer (get-buffer-create "*Buffer List*"))) + (list-buffers-internal buffer + (if (memq files-only '(t nil)) + #'(lambda (b) + (let ((n (buffer-name b))) + (cond ((and (/= 0 (length n)) + (= (aref n 0) ?\ )) + ;;don't mention if starts with " " + nil) + (files-only + (buffer-file-name b)) + (t + t)))) + files-only)) + buffer)) + +(provide 'buff-menu) + +;;; buff-menu.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/buffer.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/buffer.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,112 @@ +;;; buffer.el --- buffer routines taken from C + +;; Copyright (C) 1985-1989, 1992-1995, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995 Sun Microsystems. +;; Copyright (C) 1995, 1996 Ben Wing. + +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30 buffer.c. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +(defun switch-to-buffer (bufname &optional norecord) + "Select buffer BUFNAME in the current window. +BUFNAME may be a buffer or a buffer name. +Optional second arg NORECORD non-nil means +do not put this buffer at the front of the list of recently selected ones. + +WARNING: This is NOT the way to work on another buffer temporarily +within a Lisp program! Use `set-buffer' instead. That avoids messing with +the window-buffer correspondences." + (interactive "BSwitch to buffer: ") + ;; #ifdef I18N3 + ;; #### Doc string should indicate that the buffer name will get + ;; translated. + ;; #endif + (if (eq (minibuffer-window) (selected-window)) + (error "Cannot switch buffers in minibuffer window")) + (if (window-dedicated-p (selected-window)) + (error "Cannot switch buffers in a dedicated window")) + (let (buf) + (if (null bufname) + (setq buf (other-buffer (current-buffer))) + (setq buf (get-buffer bufname)) + (if (null buf) + (progn + (setq buf (get-buffer-create bufname)) + (set-buffer-major-mode buf)))) + (push-window-configuration) + (set-buffer buf) + (or norecord (record-buffer buf)) + (set-window-buffer (if (eq (selected-window) (minibuffer-window)) + (next-window (minibuffer-window)) + (selected-window)) + buf) + buf)) + +(defun pop-to-buffer (bufname &optional not-this-window-p on-frame) + "Select buffer BUFNAME in some window, preferably a different one. +If BUFNAME is nil, then some other buffer is chosen. +If `pop-up-windows' is non-nil, windows can be split to do this. +If optional second arg NOT-THIS-WINDOW-P is non-nil, insist on finding +another window even if BUFNAME is already visible in the selected window. +If optional third arg is non-nil, it is the frame to pop to this +buffer on. +If `focus-follows-mouse' is non-nil, keyboard focus is left unchanged." + ;; #ifdef I18N3 + ;; #### Doc string should indicate that the buffer name will get + ;; translated. + ;; #endif + ;; This is twisted. It is evil to throw the keyboard focus around + ;; willy-nilly if the user wants focus-follows-mouse. + (let ((oldbuf (current-buffer)) + buf window frame) + (if (null bufname) + (setq buf (other-buffer (current-buffer))) + (setq buf (get-buffer bufname)) + (if (null buf) + (progn + (setq buf (get-buffer-create bufname)) + (set-buffer-major-mode buf)))) + (push-window-configuration) + (set-buffer buf) + (setq window (display-buffer buf not-this-window-p on-frame)) + (setq frame (window-frame window)) + ;; if the display-buffer hook decided to show this buffer in another + ;; frame, then select that frame, (unless obeying focus-follows-mouse -sb). + (if (and (not focus-follows-mouse) + (not (eq frame (selected-frame)))) + (select-frame frame)) + (record-buffer buf) + (if (and focus-follows-mouse + on-frame + (not (eq on-frame (selected-frame)))) + (set-buffer oldbuf) + ;; select-window will modify the internal keyboard focus of XEmacs + (select-window window)) + buf)) + +;;; buffer.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/byte-optimize.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/byte-optimize.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,1956 @@ +;;; byte-opt.el --- the optimization passes of the emacs-lisp byte compiler. + +;;; Copyright (c) 1991, 1994 Free Software Foundation, Inc. + +;; Author: Jamie Zawinski +;; Hallvard Furuseth +;; Keywords: internal + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30. + +;;; Commentary: + +;;; ======================================================================== +;;; "No matter how hard you try, you can't make a racehorse out of a pig. +;;; You can, however, make a faster pig." +;;; +;;; Or, to put it another way, the emacs byte compiler is a VW Bug. This code +;;; makes it be a VW Bug with fuel injection and a turbocharger... You're +;;; still not going to make it go faster than 70 mph, but it might be easier +;;; to get it there. +;;; + +;;; TO DO: +;;; +;;; (apply '(lambda (x &rest y) ...) 1 (foo)) +;;; +;;; maintain a list of functions known not to access any global variables +;;; (actually, give them a 'dynamically-safe property) and then +;;; (let ( v1 v2 ... vM vN ) <...dynamically-safe...> ) ==> +;;; (let ( v1 v2 ... vM ) vN <...dynamically-safe...> ) +;;; by recursing on this, we might be able to eliminate the entire let. +;;; However certain variables should never have their bindings optimized +;;; away, because they affect everything. +;;; (put 'debug-on-error 'binding-is-magic t) +;;; (put 'debug-on-abort 'binding-is-magic t) +;;; (put 'debug-on-next-call 'binding-is-magic t) +;;; (put 'mocklisp-arguments 'binding-is-magic t) +;;; (put 'inhibit-quit 'binding-is-magic t) +;;; (put 'quit-flag 'binding-is-magic t) +;;; (put 't 'binding-is-magic t) +;;; (put 'nil 'binding-is-magic t) +;;; possibly also +;;; (put 'gc-cons-threshold 'binding-is-magic t) +;;; (put 'track-mouse 'binding-is-magic t) +;;; others? +;;; +;;; Simple defsubsts often produce forms like +;;; (let ((v1 (f1)) (v2 (f2)) ...) +;;; (FN v1 v2 ...)) +;;; It would be nice if we could optimize this to +;;; (FN (f1) (f2) ...) +;;; but we can't unless FN is dynamically-safe (it might be dynamically +;;; referring to the bindings that the lambda arglist established.) +;;; One of the uncountable lossages introduced by dynamic scope... +;;; +;;; Maybe there should be a control-structure that says "turn on +;;; fast-and-loose type-assumptive optimizations here." Then when +;;; we see a form like (car foo) we can from then on assume that +;;; the variable foo is of type cons, and optimize based on that. +;;; But, this won't win much because of (you guessed it) dynamic +;;; scope. Anything down the stack could change the value. +;;; (Another reason it doesn't work is that it is perfectly valid +;;; to call car with a null argument.) A better approach might +;;; be to allow type-specification of the form +;;; (put 'foo 'arg-types '(float (list integer) dynamic)) +;;; (put 'foo 'result-type 'bool) +;;; It should be possible to have these types checked to a certain +;;; degree. +;;; +;;; collapse common subexpressions +;;; +;;; It would be nice if redundant sequences could be factored out as well, +;;; when they are known to have no side-effects: +;;; (list (+ a b c) (+ a b c)) --> a b add c add dup list-2 +;;; but beware of traps like +;;; (cons (list x y) (list x y)) +;;; +;;; Tail-recursion elimination is not really possible in Emacs Lisp. +;;; Tail-recursion elimination is almost always impossible when all variables +;;; have dynamic scope, but given that the "return" byteop requires the +;;; binding stack to be empty (rather than emptying it itself), there can be +;;; no truly tail-recursive Emacs Lisp functions that take any arguments or +;;; make any bindings. +;;; +;;; Here is an example of an Emacs Lisp function which could safely be +;;; byte-compiled tail-recursively: +;;; +;;; (defun tail-map (fn list) +;;; (cond (list +;;; (funcall fn (car list)) +;;; (tail-map fn (cdr list))))) +;;; +;;; However, if there was even a single let-binding around the COND, +;;; it could not be byte-compiled, because there would be an "unbind" +;;; byte-op between the final "call" and "return." Adding a +;;; Bunbind_all byteop would fix this. +;;; +;;; (defun foo (x y z) ... (foo a b c)) +;;; ... (const foo) (varref a) (varref b) (varref c) (call 3) END: (return) +;;; ... (varref a) (varbind x) (varref b) (varbind y) (varref c) (varbind z) (goto 0) END: (unbind-all) (return) +;;; ... (varref a) (varset x) (varref b) (varset y) (varref c) (varset z) (goto 0) END: (return) +;;; +;;; this also can be considered tail recursion: +;;; +;;; ... (const foo) (varref a) (call 1) (goto X) ... X: (return) +;;; could generalize this by doing the optimization +;;; (goto X) ... X: (return) --> (return) +;;; +;;; But this doesn't solve all of the problems: although by doing tail- +;;; recursion elimination in this way, the call-stack does not grow, the +;;; binding-stack would grow with each recursive step, and would eventually +;;; overflow. I don't believe there is any way around this without lexical +;;; scope. +;;; +;;; Wouldn't it be nice if Emacs Lisp had lexical scope. +;;; +;;; Idea: the form (lexical-scope) in a file means that the file may be +;;; compiled lexically. This proclamation is file-local. Then, within +;;; that file, "let" would establish lexical bindings, and "let-dynamic" +;;; would do things the old way. (Or we could use CL "declare" forms.) +;;; We'd have to notice defvars and defconsts, since those variables should +;;; always be dynamic, and attempting to do a lexical binding of them +;;; should simply do a dynamic binding instead. +;;; But! We need to know about variables that were not necessarily defvarred +;;; in the file being compiled (doing a boundp check isn't good enough.) +;;; Fdefvar() would have to be modified to add something to the plist. +;;; +;;; A major disadvantage of this scheme is that the interpreter and compiler +;;; would have different semantics for files compiled with (dynamic-scope). +;;; Since this would be a file-local optimization, there would be no way to +;;; modify the interpreter to obey this (unless the loader was hacked +;;; in some grody way, but that's a really bad idea.) +;;; +;;; HA! HA! HA! RMS removed the following paragraph from his version of +;;; byte-opt.el, proving once again his stubborn refusal to accept any +;;; developments in computer science that occurred after the late 1970's. +;;; +;;; Really the Right Thing is to make lexical scope the default across +;;; the board, in the interpreter and compiler, and just FIX all of +;;; the code that relies on dynamic scope of non-defvarred variables. + +;; Other things to consider: + +;;;;; Associative math should recognize subcalls to identical function: +;;;(disassemble (lambda (x) (+ (+ (foo) 1) (+ (bar) 2)))) +;;;;; This should generate the same as (1+ x) and (1- x) + +;;;(disassemble (lambda (x) (cons (+ x 1) (- x 1)))) +;;;;; An awful lot of functions always return a non-nil value. If they're +;;;;; error free also they may act as true-constants. + +;;;(disassemble (lambda (x) (and (point) (foo)))) +;;;;; When +;;;;; - all but one arguments to a function are constant +;;;;; - the non-constant argument is an if-expression (cond-expression?) +;;;;; then the outer function can be distributed. If the guarding +;;;;; condition is side-effect-free [assignment-free] then the other +;;;;; arguments may be any expressions. Since, however, the code size +;;;;; can increase this way they should be "simple". Compare: + +;;;(disassemble (lambda (x) (eq (if (point) 'a 'b) 'c))) +;;;(disassemble (lambda (x) (if (point) (eq 'a 'c) (eq 'b 'c)))) + +;;;;; (car (cons A B)) -> (progn B A) +;;;(disassemble (lambda (x) (car (cons (foo) 42)))) + +;;;;; (cdr (cons A B)) -> (progn A B) +;;;(disassemble (lambda (x) (cdr (cons 42 (foo))))) + +;;;;; (car (list A B ...)) -> (progn B ... A) +;;;(disassemble (lambda (x) (car (list (foo) 42 (bar))))) + +;;;;; (cdr (list A B ...)) -> (progn A (list B ...)) +;;;(disassemble (lambda (x) (cdr (list 42 (foo) (bar))))) + + +;;; Code: + +(require 'byte-compile "bytecomp") + +(defun byte-compile-log-lap-1 (format &rest args) + (if (aref byte-code-vector 0) + (error "The old version of the disassembler is loaded. Reload new-bytecomp as well.")) + (byte-compile-log-1 + (apply 'format format + (let (c a) + (mapcar '(lambda (arg) + (if (not (consp arg)) + (if (and (symbolp arg) + (string-match "^byte-" (symbol-name arg))) + (intern (substring (symbol-name arg) 5)) + arg) + (if (integerp (setq c (car arg))) + (error "non-symbolic byte-op %s" c)) + (if (eq c 'TAG) + (setq c arg) + (setq a (cond ((memq c byte-goto-ops) + (car (cdr (cdr arg)))) + ((memq c byte-constref-ops) + (car (cdr arg))) + (t (cdr arg)))) + (setq c (symbol-name c)) + (if (string-match "^byte-." c) + (setq c (intern (substring c 5))))) + (if (eq c 'constant) (setq c 'const)) + (if (and (eq (cdr arg) 0) + (not (memq c '(unbind call const)))) + c + (format "(%s %s)" c a)))) + args))))) + +(defmacro byte-compile-log-lap (format-string &rest args) + (list 'and + '(memq byte-optimize-log '(t byte)) + (cons 'byte-compile-log-lap-1 + (cons format-string args)))) + + +;;; byte-compile optimizers to support inlining + +(put 'inline 'byte-optimizer 'byte-optimize-inline-handler) + +(defun byte-optimize-inline-handler (form) + "byte-optimize-handler for the `inline' special-form." + (cons 'progn + (mapcar + '(lambda (sexp) + (let ((fn (car-safe sexp))) + (if (and (symbolp fn) + (or (cdr (assq fn byte-compile-function-environment)) + (and (fboundp fn) + (not (or (cdr (assq fn byte-compile-macro-environment)) + (and (consp (setq fn (symbol-function fn))) + (eq (car fn) 'macro)) + (subrp fn)))))) + (byte-compile-inline-expand sexp) + sexp))) + (cdr form)))) + + +;; Splice the given lap code into the current instruction stream. +;; If it has any labels in it, you're responsible for making sure there +;; are no collisions, and that byte-compile-tag-number is reasonable +;; after this is spliced in. The provided list is destroyed. +(defun byte-inline-lapcode (lap) + (setq byte-compile-output (nconc (nreverse lap) byte-compile-output))) + + +(defun byte-compile-inline-expand (form) + (let* ((name (car form)) + (fn (or (cdr (assq name byte-compile-function-environment)) + (and (fboundp name) (symbol-function name))))) + (if (null fn) + (progn + (byte-compile-warn "attempt to inline %s before it was defined" name) + form) + ;; else + (if (and (consp fn) (eq (car fn) 'autoload)) + (progn + (load (nth 1 fn)) + (setq fn (or (cdr (assq name byte-compile-function-environment)) + (and (fboundp name) (symbol-function name)))))) + (if (and (consp fn) (eq (car fn) 'autoload)) + (error "file \"%s\" didn't define \"%s\"" (nth 1 fn) name)) + (if (symbolp fn) + (byte-compile-inline-expand (cons fn (cdr form))) + (if (compiled-function-p fn) + (progn + (fetch-bytecode fn) + (cons (list 'lambda (compiled-function-arglist fn) + (list 'byte-code + (compiled-function-instructions fn) + (compiled-function-constants fn) + (compiled-function-stack-depth fn))) + (cdr form))) + (if (not (eq (car fn) 'lambda)) (error "%s is not a lambda" name)) + (cons fn (cdr form))))))) + +;;; ((lambda ...) ...) +;;; +(defun byte-compile-unfold-lambda (form &optional name) + (or name (setq name "anonymous lambda")) + (let ((lambda (car form)) + (values (cdr form))) + (if (compiled-function-p lambda) + (setq lambda (list 'lambda (compiled-function-arglist lambda) + (list 'byte-code + (compiled-function-instructions lambda) + (compiled-function-constants lambda) + (compiled-function-stack-depth lambda))))) + (let ((arglist (nth 1 lambda)) + (body (cdr (cdr lambda))) + optionalp restp + bindings) + (if (and (stringp (car body)) (cdr body)) + (setq body (cdr body))) + (if (and (consp (car body)) (eq 'interactive (car (car body)))) + (setq body (cdr body))) + (while arglist + (cond ((eq (car arglist) '&optional) + ;; ok, I'll let this slide because funcall_lambda() does... + ;; (if optionalp (error "multiple &optional keywords in %s" name)) + (if restp (error "&optional found after &rest in %s" name)) + (if (null (cdr arglist)) + (error "nothing after &optional in %s" name)) + (setq optionalp t)) + ((eq (car arglist) '&rest) + ;; ...but it is by no stretch of the imagination a reasonable + ;; thing that funcall_lambda() allows (&rest x y) and + ;; (&rest x &optional y) in arglists. + (if (null (cdr arglist)) + (error "nothing after &rest in %s" name)) + (if (cdr (cdr arglist)) + (error "multiple vars after &rest in %s" name)) + (setq restp t)) + (restp + (setq bindings (cons (list (car arglist) + (and values (cons 'list values))) + bindings) + values nil)) + ((and (not optionalp) (null values)) + (byte-compile-warn "attempt to open-code %s with too few arguments" name) + (setq arglist nil values 'too-few)) + (t + (setq bindings (cons (list (car arglist) (car values)) + bindings) + values (cdr values)))) + (setq arglist (cdr arglist))) + (if values + (progn + (or (eq values 'too-few) + (byte-compile-warn + "attempt to open-code %s with too many arguments" name)) + form) + (let ((newform + (if bindings + (cons 'let (cons (nreverse bindings) body)) + (cons 'progn body)))) + (byte-compile-log " %s\t==>\t%s" form newform) + newform))))) + + +;;; implementing source-level optimizers + +(defun byte-optimize-form-code-walker (form for-effect) + ;; + ;; For normal function calls, We can just mapcar the optimizer the cdr. But + ;; we need to have special knowledge of the syntax of the special forms + ;; like let and defun (that's why they're special forms :-). (Actually, + ;; the important aspect is that they are subrs that don't evaluate all of + ;; their args.) + ;; + (let ((fn (car-safe form)) + tmp) + (cond ((not (consp form)) + (if (not (and for-effect + (or byte-compile-delete-errors + (not (symbolp form)) + (eq form t)))) + form)) + ((eq fn 'quote) + (if (cdr (cdr form)) + (byte-compile-warn "malformed quote form: %s" + (prin1-to-string form))) + ;; map (quote nil) to nil to simplify optimizer logic. + ;; map quoted constants to nil if for-effect (just because). + (and (nth 1 form) + (not for-effect) + form)) + ((or (compiled-function-p fn) + (eq 'lambda (car-safe fn))) + (byte-compile-unfold-lambda form)) + ((memq fn '(let let*)) + ;; recursively enter the optimizer for the bindings and body + ;; of a let or let*. This for depth-firstness: forms that + ;; are more deeply nested are optimized first. + (cons fn + (cons + (mapcar '(lambda (binding) + (if (symbolp binding) + binding + (if (cdr (cdr binding)) + (byte-compile-warn "malformed let binding: %s" + (prin1-to-string binding))) + (list (car binding) + (byte-optimize-form (nth 1 binding) nil)))) + (nth 1 form)) + (byte-optimize-body (cdr (cdr form)) for-effect)))) + ((eq fn 'cond) + (cons fn + (mapcar '(lambda (clause) + (if (consp clause) + (cons + (byte-optimize-form (car clause) nil) + (byte-optimize-body (cdr clause) for-effect)) + (byte-compile-warn "malformed cond form: %s" + (prin1-to-string clause)) + clause)) + (cdr form)))) + ((eq fn 'progn) + ;; as an extra added bonus, this simplifies (progn ) --> + (if (cdr (cdr form)) + (progn + (setq tmp (byte-optimize-body (cdr form) for-effect)) + (if (cdr tmp) (cons 'progn tmp) (car tmp))) + (byte-optimize-form (nth 1 form) for-effect))) + ((eq fn 'prog1) + (if (cdr (cdr form)) + (cons 'prog1 + (cons (byte-optimize-form (nth 1 form) for-effect) + (byte-optimize-body (cdr (cdr form)) t))) + (byte-optimize-form (nth 1 form) for-effect))) + ((eq fn 'prog2) + (cons 'prog2 + (cons (byte-optimize-form (nth 1 form) t) + (cons (byte-optimize-form (nth 2 form) for-effect) + (byte-optimize-body (cdr (cdr (cdr form))) t))))) + + ((memq fn '(save-excursion save-restriction save-current-buffer)) + ;; those subrs which have an implicit progn; it's not quite good + ;; enough to treat these like normal function calls. + ;; This can turn (save-excursion ...) into (save-excursion) which + ;; will be optimized away in the lap-optimize pass. + (cons fn (byte-optimize-body (cdr form) for-effect))) + + ((eq fn 'with-output-to-temp-buffer) + ;; this is just like the above, except for the first argument. + (cons fn + (cons + (byte-optimize-form (nth 1 form) nil) + (byte-optimize-body (cdr (cdr form)) for-effect)))) + + ((eq fn 'if) + (cons fn + (cons (byte-optimize-form (nth 1 form) nil) + (cons + (byte-optimize-form (nth 2 form) for-effect) + (byte-optimize-body (nthcdr 3 form) for-effect))))) + + ((memq fn '(and or)) ; remember, and/or are control structures. + ;; take forms off the back until we can't any more. + ;; In the future it could conceivably be a problem that the + ;; subexpressions of these forms are optimized in the reverse + ;; order, but it's ok for now. + (if for-effect + (let ((backwards (reverse (cdr form)))) + (while (and backwards + (null (setcar backwards + (byte-optimize-form (car backwards) + for-effect)))) + (setq backwards (cdr backwards))) + (if (and (cdr form) (null backwards)) + (byte-compile-log + " all subforms of %s called for effect; deleted" form)) + (and backwards + (cons fn (nreverse backwards)))) + (cons fn (mapcar 'byte-optimize-form (cdr form))))) + + ((eq fn 'interactive) + (byte-compile-warn "misplaced interactive spec: %s" + (prin1-to-string form)) + nil) + + ((memq fn '(defun defmacro function + condition-case save-window-excursion)) + ;; These forms are compiled as constants or by breaking out + ;; all the subexpressions and compiling them separately. + form) + + ((eq fn 'unwind-protect) + ;; the "protected" part of an unwind-protect is compiled (and thus + ;; optimized) as a top-level form, so don't do it here. But the + ;; non-protected part has the same for-effect status as the + ;; unwind-protect itself. (The protected part is always for effect, + ;; but that isn't handled properly yet.) + (cons fn + (cons (byte-optimize-form (nth 1 form) for-effect) + (cdr (cdr form))))) + + ((eq fn 'catch) + ;; the body of a catch is compiled (and thus optimized) as a + ;; top-level form, so don't do it here. The tag is never + ;; for-effect. The body should have the same for-effect status + ;; as the catch form itself, but that isn't handled properly yet. + (cons fn + (cons (byte-optimize-form (nth 1 form) nil) + (cdr (cdr form))))) + + ;; If optimization is on, this is the only place that macros are + ;; expanded. If optimization is off, then macroexpansion happens + ;; in byte-compile-form. Otherwise, the macros are already expanded + ;; by the time that is reached. + ((not (eq form + (setq form (macroexpand form + byte-compile-macro-environment)))) + (byte-optimize-form form for-effect)) + + ((not (symbolp fn)) + (or (eq 'mocklisp (car-safe fn)) ; ha! + (byte-compile-warn "%s is a malformed function" + (prin1-to-string fn))) + form) + + ((and for-effect (setq tmp (get fn 'side-effect-free)) + (or byte-compile-delete-errors + (eq tmp 'error-free) + (progn + (byte-compile-warn "%s called for effect" + (prin1-to-string form)) + nil))) + (byte-compile-log " %s called for effect; deleted" fn) + ;; appending a nil here might not be necessary, but it can't hurt. + (byte-optimize-form + (cons 'progn (append (cdr form) '(nil))) t)) + + (t + ;; Otherwise, no args can be considered to be for-effect, + ;; even if the called function is for-effect, because we + ;; don't know anything about that function. + (cons fn (mapcar 'byte-optimize-form (cdr form))))))) + + +(defun byte-optimize-form (form &optional for-effect) + "The source-level pass of the optimizer." + ;; + ;; First, optimize all sub-forms of this one. + (setq form (byte-optimize-form-code-walker form for-effect)) + ;; + ;; after optimizing all subforms, optimize this form until it doesn't + ;; optimize any further. This means that some forms will be passed through + ;; the optimizer many times, but that's necessary to make the for-effect + ;; processing do as much as possible. + ;; + (let (opt new) + (if (and (consp form) + (symbolp (car form)) + (or (and for-effect + ;; we don't have any of these yet, but we might. + (setq opt (get (car form) 'byte-for-effect-optimizer))) + (setq opt (get (car form) 'byte-optimizer))) + (not (eq form (setq new (funcall opt form))))) + (progn +;; (if (equal form new) (error "bogus optimizer -- %s" opt)) + (byte-compile-log " %s\t==>\t%s" form new) + (setq new (byte-optimize-form new for-effect)) + new) + form))) + + +(defun byte-optimize-body (forms all-for-effect) + ;; optimize the cdr of a progn or implicit progn; all forms is a list of + ;; forms, all but the last of which are optimized with the assumption that + ;; they are being called for effect. the last is for-effect as well if + ;; all-for-effect is true. returns a new list of forms. + (let ((rest forms) + (result nil) + fe new) + (while rest + (setq fe (or all-for-effect (cdr rest))) + (setq new (and (car rest) (byte-optimize-form (car rest) fe))) + (if (or new (not fe)) + (setq result (cons new result))) + (setq rest (cdr rest))) + (nreverse result))) + + +;;; some source-level optimizers +;;; +;;; when writing optimizers, be VERY careful that the optimizer returns +;;; something not EQ to its argument if and ONLY if it has made a change. +;;; This implies that you cannot simply destructively modify the list; +;;; you must return something not EQ to it if you make an optimization. +;;; +;;; It is now safe to optimize code such that it introduces new bindings. + +;; I'd like this to be a defsubst, but let's not be self-referential... +(defmacro byte-compile-trueconstp (form) + ;; Returns non-nil if FORM is a non-nil constant. + (` (cond ((consp (, form)) (eq (car (, form)) 'quote)) + ((not (symbolp (, form)))) + ((eq (, form) t))))) + +;; If the function is being called with constant numeric args, +;; evaluate as much as possible at compile-time. This optimizer +;; assumes that the function is associative, like + or *. +(defun byte-optimize-associative-math (form) + (let ((args nil) + (constants nil) + (rest (cdr form))) + (while rest + (if (numberp (car rest)) + (setq constants (cons (car rest) constants)) + (setq args (cons (car rest) args))) + (setq rest (cdr rest))) + (if (cdr constants) + (if args + (list (car form) + (apply (car form) constants) + (if (cdr args) + (cons (car form) (nreverse args)) + (car args))) + (apply (car form) constants)) + form))) + +;; If the function is being called with constant numeric args, +;; evaluate as much as possible at compile-time. This optimizer +;; assumes that the function satisfies +;; (op x1 x2 ... xn) == (op ...(op (op x1 x2) x3) ...xn) +;; like - and /. +(defun byte-optimize-nonassociative-math (form) + (if (or (not (numberp (car (cdr form)))) + (not (numberp (car (cdr (cdr form)))))) + form + (let ((constant (car (cdr form))) + (rest (cdr (cdr form)))) + (while (numberp (car rest)) + (setq constant (funcall (car form) constant (car rest)) + rest (cdr rest))) + (if rest + (cons (car form) (cons constant rest)) + constant)))) + +;;(defun byte-optimize-associative-two-args-math (form) +;; (setq form (byte-optimize-associative-math form)) +;; (if (consp form) +;; (byte-optimize-two-args-left form) +;; form)) + +;;(defun byte-optimize-nonassociative-two-args-math (form) +;; (setq form (byte-optimize-nonassociative-math form)) +;; (if (consp form) +;; (byte-optimize-two-args-right form) +;; form)) + +;; jwz: (byte-optimize-approx-equal 0.0 0.0) was returning nil +;; in xemacs 19.15 because it used < instead of <=. +(defun byte-optimize-approx-equal (x y) + (<= (* (abs (- x y)) 100) (abs (+ x y)))) + +;; Collect all the constants from FORM, after the STARTth arg, +;; and apply FUN to them to make one argument at the end. +;; For functions that can handle floats, that optimization +;; can be incorrect because reordering can cause an overflow +;; that would otherwise be avoided by encountering an arg that is a float. +;; We avoid this problem by (1) not moving float constants and +;; (2) not moving anything if it would cause an overflow. +(defun byte-optimize-delay-constants-math (form start fun) + ;; Merge all FORM's constants from number START, call FUN on them + ;; and put the result at the end. + (let ((rest (nthcdr (1- start) form)) + (orig form) + ;; t means we must check for overflow. + (overflow (memq fun '(+ *)))) + (while (cdr (setq rest (cdr rest))) + (if (integerp (car rest)) + (let (constants) + (setq form (copy-sequence form) + rest (nthcdr (1- start) form)) + (while (setq rest (cdr rest)) + (cond ((integerp (car rest)) + (setq constants (cons (car rest) constants)) + (setcar rest nil)))) + ;; If necessary, check now for overflow + ;; that might be caused by reordering. + (if (and overflow + ;; We have overflow if the result of doing the arithmetic + ;; on floats is not even close to the result + ;; of doing it on integers. + (not (byte-optimize-approx-equal + (apply fun (mapcar 'float constants)) + (float (apply fun constants))))) + (setq form orig) + (setq form (nconc (delq nil form) + (list (apply fun (nreverse constants))))))))) + form)) + +(defun byte-optimize-plus (form) + (setq form (byte-optimize-delay-constants-math form 1 '+)) + (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) + ;;(setq form (byte-optimize-associative-two-args-math form)) + (cond ((null (cdr form)) + (condition-case () + (eval form) + (error form))) + + ;; `add1' and `sub1' are a marginally fewer instructions + ;; than `plus' and `minus', so use them when possible. + ((and (null (nthcdr 3 form)) + (eq (nth 2 form) 1)) + (list '1+ (nth 1 form))) ; (+ x 1) --> (1+ x) + ((and (null (nthcdr 3 form)) + (eq (nth 1 form) 1)) + (list '1+ (nth 2 form))) ; (+ 1 x) --> (1+ x) + ((and (null (nthcdr 3 form)) + (eq (nth 2 form) -1)) + (list '1- (nth 1 form))) ; (+ x -1) --> (1- x) + ((and (null (nthcdr 3 form)) + (eq (nth 1 form) -1)) + (list '1- (nth 2 form))) ; (+ -1 x) --> (1- x) + +;;; It is not safe to delete the function entirely +;;; (actually, it would be safe if we know the sole arg +;;; is not a marker). +;; ((null (cdr (cdr form))) (nth 1 form)) + (t form))) + +(defun byte-optimize-minus (form) + ;; Put constants at the end, except the last constant. + (setq form (byte-optimize-delay-constants-math form 2 '+)) + ;; Now only first and last element can be a number. + (let ((last (car (reverse (nthcdr 3 form))))) + (cond ((eq 0 last) + ;; (- x y ... 0) --> (- x y ...) + (setq form (copy-sequence form)) + (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form)))) + ;; If form is (- CONST foo... CONST), merge first and last. + ((and (numberp (nth 1 form)) + (numberp last)) + (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form)) + (delq last (copy-sequence (nthcdr 3 form)))))))) + (setq form +;;; It is not safe to delete the function entirely +;;; (actually, it would be safe if we know the sole arg +;;; is not a marker). +;;; (if (eq (nth 2 form) 0) +;;; (nth 1 form) ; (- x 0) --> x + (byte-optimize-predicate + (if (and (null (cdr (cdr (cdr form)))) + (eq (nth 1 form) 0)) ; (- 0 x) --> (- x) + (cons (car form) (cdr (cdr form))) + form)) +;;; ) + ) + + ;; `add1' and `sub1' are a marginally fewer instructions than `plus' + ;; and `minus', so use them when possible. + (cond ((and (null (nthcdr 3 form)) + (eq (nth 2 form) 1)) + (list '1- (nth 1 form))) ; (- x 1) --> (1- x) + ((and (null (nthcdr 3 form)) + (eq (nth 2 form) -1)) + (list '1+ (nth 1 form))) ; (- x -1) --> (1+ x) + (t + form)) + ) + +(defun byte-optimize-multiply (form) + (setq form (byte-optimize-delay-constants-math form 1 '*)) + ;; If there is a constant in FORM, it is now the last element. + (cond ((null (cdr form)) 1) +;;; It is not safe to delete the function entirely +;;; (actually, it would be safe if we know the sole arg +;;; is not a marker or if it appears in other arithmetic). +;;; ((null (cdr (cdr form))) (nth 1 form)) + ((let ((last (car (reverse form)))) + (cond ((eq 0 last) (cons 'progn (cdr form))) + ((eq 1 last) (delq 1 (copy-sequence form))) + ((eq -1 last) (list '- (delq -1 (copy-sequence form)))) + ((and (eq 2 last) + (memq t (mapcar 'symbolp (cdr form)))) + (prog1 (setq form (delq 2 (copy-sequence form))) + (while (not (symbolp (car (setq form (cdr form)))))) + (setcar form (list '+ (car form) (car form))))) + (form)))))) + +(defsubst byte-compile-butlast (form) + (nreverse (cdr (reverse form)))) + +(defun byte-optimize-divide (form) + (setq form (byte-optimize-delay-constants-math form 2 '*)) + (let ((last (car (reverse (cdr (cdr form)))))) + (if (numberp last) + (cond ((= (length form) 3) + (if (and (numberp (nth 1 form)) + (not (zerop last)) + (condition-case nil + (/ (nth 1 form) last) + (error nil))) + (setq form (list 'progn (/ (nth 1 form) last))))) + ((= last 1) + (setq form (byte-compile-butlast form))) + ((numberp (nth 1 form)) + (setq form (cons (car form) + (cons (/ (nth 1 form) last) + (byte-compile-butlast (cdr (cdr form))))) + last nil)))) + (cond +;;; ((null (cdr (cdr form))) +;;; (nth 1 form)) + ((eq (nth 1 form) 0) + (append '(progn) (cdr (cdr form)) '(0))) + ((eq last -1) + (list '- (if (nthcdr 3 form) + (byte-compile-butlast form) + (nth 1 form)))) + (form)))) + +(defun byte-optimize-logmumble (form) + (setq form (byte-optimize-delay-constants-math form 1 (car form))) + (byte-optimize-predicate + (cond ((memq 0 form) + (setq form (if (eq (car form) 'logand) + (cons 'progn (cdr form)) + (delq 0 (copy-sequence form))))) + ((and (eq (car-safe form) 'logior) + (memq -1 form)) + (cons 'progn (cdr form))) + (form)))) + + +(defun byte-optimize-binary-predicate (form) + (if (byte-compile-constp (nth 1 form)) + (if (byte-compile-constp (nth 2 form)) + (condition-case () + (list 'quote (eval form)) + (error form)) + ;; This can enable some lapcode optimizations. + (list (car form) (nth 2 form) (nth 1 form))) + form)) + +(defun byte-optimize-predicate (form) + (let ((ok t) + (rest (cdr form))) + (while (and rest ok) + (setq ok (byte-compile-constp (car rest)) + rest (cdr rest))) + (if ok + (condition-case () + (list 'quote (eval form)) + (error form)) + form))) + +(defun byte-optimize-identity (form) + (if (and (cdr form) (null (cdr (cdr form)))) + (nth 1 form) + (byte-compile-warn "identity called with %d arg%s, but requires 1" + (length (cdr form)) + (if (= 1 (length (cdr form))) "" "s")) + form)) + +(put 'identity 'byte-optimizer 'byte-optimize-identity) + +(put '+ 'byte-optimizer 'byte-optimize-plus) +(put '* 'byte-optimizer 'byte-optimize-multiply) +(put '- 'byte-optimizer 'byte-optimize-minus) +(put '/ 'byte-optimizer 'byte-optimize-divide) +(put 'max 'byte-optimizer 'byte-optimize-associative-math) +(put 'min 'byte-optimizer 'byte-optimize-associative-math) + +(put '= 'byte-optimizer 'byte-optimize-binary-predicate) +(put 'eq 'byte-optimizer 'byte-optimize-binary-predicate) +(put 'eql 'byte-optimizer 'byte-optimize-binary-predicate) +(put 'equal 'byte-optimizer 'byte-optimize-binary-predicate) +(put 'string= 'byte-optimizer 'byte-optimize-binary-predicate) +(put 'string-equal 'byte-optimizer 'byte-optimize-binary-predicate) + +(put '< 'byte-optimizer 'byte-optimize-predicate) +(put '> 'byte-optimizer 'byte-optimize-predicate) +(put '<= 'byte-optimizer 'byte-optimize-predicate) +(put '>= 'byte-optimizer 'byte-optimize-predicate) +(put '1+ 'byte-optimizer 'byte-optimize-predicate) +(put '1- 'byte-optimizer 'byte-optimize-predicate) +(put 'not 'byte-optimizer 'byte-optimize-predicate) +(put 'null 'byte-optimizer 'byte-optimize-predicate) +(put 'memq 'byte-optimizer 'byte-optimize-predicate) +(put 'consp 'byte-optimizer 'byte-optimize-predicate) +(put 'listp 'byte-optimizer 'byte-optimize-predicate) +(put 'symbolp 'byte-optimizer 'byte-optimize-predicate) +(put 'stringp 'byte-optimizer 'byte-optimize-predicate) +(put 'string< 'byte-optimizer 'byte-optimize-predicate) +(put 'string-lessp 'byte-optimizer 'byte-optimize-predicate) + +(put 'logand 'byte-optimizer 'byte-optimize-logmumble) +(put 'logior 'byte-optimizer 'byte-optimize-logmumble) +(put 'logxor 'byte-optimizer 'byte-optimize-logmumble) +(put 'lognot 'byte-optimizer 'byte-optimize-predicate) + +(put 'car 'byte-optimizer 'byte-optimize-predicate) +(put 'cdr 'byte-optimizer 'byte-optimize-predicate) +(put 'car-safe 'byte-optimizer 'byte-optimize-predicate) +(put 'cdr-safe 'byte-optimizer 'byte-optimize-predicate) + + +;; I'm not convinced that this is necessary. Doesn't the optimizer loop +;; take care of this? - Jamie +;; I think this may some times be necessary to reduce ie (quote 5) to 5, +;; so arithmetic optimizers recognize the numeric constant. - Hallvard +(put 'quote 'byte-optimizer 'byte-optimize-quote) +(defun byte-optimize-quote (form) + (if (or (consp (nth 1 form)) + (and (symbolp (nth 1 form)) + ;; XEmacs addition: + (not (keywordp (nth 1 form))) + (not (memq (nth 1 form) '(nil t))))) + form + (nth 1 form))) + +(defun byte-optimize-zerop (form) + (cond ((numberp (nth 1 form)) + (eval form)) + (byte-compile-delete-errors + (list '= (nth 1 form) 0)) + (form))) + +(put 'zerop 'byte-optimizer 'byte-optimize-zerop) + +(defun byte-optimize-and (form) + ;; Simplify if less than 2 args. + ;; if there is a literal nil in the args to `and', throw it and following + ;; forms away, and surround the `and' with (progn ... nil). + (cond ((null (cdr form))) + ((memq nil form) + (list 'progn + (byte-optimize-and + (prog1 (setq form (copy-sequence form)) + (while (nth 1 form) + (setq form (cdr form))) + (setcdr form nil))) + nil)) + ((null (cdr (cdr form))) + (nth 1 form)) + ((byte-optimize-predicate form)))) + +(defun byte-optimize-or (form) + ;; Throw away nil's, and simplify if less than 2 args. + ;; If there is a literal non-nil constant in the args to `or', throw away all + ;; following forms. + (if (memq nil form) + (setq form (delq nil (copy-sequence form)))) + (let ((rest form)) + (while (cdr (setq rest (cdr rest))) + (if (byte-compile-trueconstp (car rest)) + (setq form (copy-sequence form) + rest (setcdr (memq (car rest) form) nil)))) + (if (cdr (cdr form)) + (byte-optimize-predicate form) + (nth 1 form)))) + +(defun byte-optimize-cond (form) + ;; if any clauses have a literal nil as their test, throw them away. + ;; if any clause has a literal non-nil constant as its test, throw + ;; away all following clauses. + (let (rest) + ;; This must be first, to reduce (cond (t ...) (nil)) to (progn t ...) + (while (setq rest (assq nil (cdr form))) + (setq form (delq rest (copy-sequence form)))) + (if (memq nil (cdr form)) + (setq form (delq nil (copy-sequence form)))) + (setq rest form) + (while (setq rest (cdr rest)) + (cond ((byte-compile-trueconstp (car-safe (car rest))) + (cond ((eq rest (cdr form)) + (setq form + (if (cdr (car rest)) + (if (cdr (cdr (car rest))) + (cons 'progn (cdr (car rest))) + (nth 1 (car rest))) + (car (car rest))))) + ((cdr rest) + (setq form (copy-sequence form)) + (setcdr (memq (car rest) form) nil))) + (setq rest nil))))) + ;; + ;; Turn (cond (( )) ... ) into (or (cond ... )) + (if (eq 'cond (car-safe form)) + (let ((clauses (cdr form))) + (if (and (consp (car clauses)) + (null (cdr (car clauses)))) + (list 'or (car (car clauses)) + (byte-optimize-cond + (cons (car form) (cdr (cdr form))))) + form)) + form)) + +(defun byte-optimize-if (form) + ;; (if ) ==> + ;; (if ) ==> (progn ) + ;; (if nil ) ==> (if (not ) (progn )) + ;; (if nil) ==> (if ) + (let ((clause (nth 1 form))) + (cond ((byte-compile-trueconstp clause) + (nth 2 form)) + ((null clause) + (if (nthcdr 4 form) + (cons 'progn (nthcdr 3 form)) + (nth 3 form))) + ((nth 2 form) + (if (equal '(nil) (nthcdr 3 form)) + (list 'if clause (nth 2 form)) + form)) + ((or (nth 3 form) (nthcdr 4 form)) + (list 'if + ;; Don't make a double negative; + ;; instead, take away the one that is there. + (if (and (consp clause) (memq (car clause) '(not null)) + (= (length clause) 2)) ; (not xxxx) or (not (xxxx)) + (nth 1 clause) + (list 'not clause)) + (if (nthcdr 4 form) + (cons 'progn (nthcdr 3 form)) + (nth 3 form)))) + (t + (list 'progn clause nil))))) + +(defun byte-optimize-while (form) + (if (nth 1 form) + form)) + +(put 'and 'byte-optimizer 'byte-optimize-and) +(put 'or 'byte-optimizer 'byte-optimize-or) +(put 'cond 'byte-optimizer 'byte-optimize-cond) +(put 'if 'byte-optimizer 'byte-optimize-if) +(put 'while 'byte-optimizer 'byte-optimize-while) + +;; byte-compile-negation-optimizer lives in bytecomp.el +(put '/= 'byte-optimizer 'byte-compile-negation-optimizer) +(put 'atom 'byte-optimizer 'byte-compile-negation-optimizer) +(put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer) + + +(defun byte-optimize-funcall (form) + ;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...) + ;; (funcall 'foo ...) ==> (foo ...) + (let ((fn (nth 1 form))) + (if (memq (car-safe fn) '(quote function)) + (cons (nth 1 fn) (cdr (cdr form))) + form))) + +(defun byte-optimize-apply (form) + ;; If the last arg is a literal constant, turn this into a funcall. + ;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...). + (let ((fn (nth 1 form)) + (last (nth (1- (length form)) form))) ; I think this really is fastest + (or (if (or (null last) + (eq (car-safe last) 'quote)) + (if (listp (nth 1 last)) + (let ((butlast (nreverse (cdr (reverse (cdr (cdr form))))))) + (nconc (list 'funcall fn) butlast + (mapcar '(lambda (x) (list 'quote x)) (nth 1 last)))) + (byte-compile-warn + "last arg to apply can't be a literal atom: %s" + (prin1-to-string last)) + nil)) + form))) + +(put 'funcall 'byte-optimizer 'byte-optimize-funcall) +(put 'apply 'byte-optimizer 'byte-optimize-apply) + + +(put 'let 'byte-optimizer 'byte-optimize-letX) +(put 'let* 'byte-optimizer 'byte-optimize-letX) +(defun byte-optimize-letX (form) + (cond ((null (nth 1 form)) + ;; No bindings + (cons 'progn (cdr (cdr form)))) + ((or (nth 2 form) (nthcdr 3 form)) + form) + ;; The body is nil + ((eq (car form) 'let) + (append '(progn) (mapcar 'car-safe (mapcar 'cdr-safe (nth 1 form))) + '(nil))) + (t + (let ((binds (reverse (nth 1 form)))) + (list 'let* (reverse (cdr binds)) (nth 1 (car binds)) nil))))) + + +(put 'nth 'byte-optimizer 'byte-optimize-nth) +(defun byte-optimize-nth (form) + (if (and (= (safe-length form) 3) (memq (nth 1 form) '(0 1))) + (list 'car (if (zerop (nth 1 form)) + (nth 2 form) + (list 'cdr (nth 2 form)))) + (byte-optimize-predicate form))) + +(put 'nthcdr 'byte-optimizer 'byte-optimize-nthcdr) +(defun byte-optimize-nthcdr (form) + (if (and (= (safe-length form) 3) (not (memq (nth 1 form) '(0 1 2)))) + (byte-optimize-predicate form) + (let ((count (nth 1 form))) + (setq form (nth 2 form)) + (while (>= (setq count (1- count)) 0) + (setq form (list 'cdr form))) + form))) + +;;; enumerating those functions which need not be called if the returned +;;; value is not used. That is, something like +;;; (progn (list (something-with-side-effects) (yow)) +;;; (foo)) +;;; may safely be turned into +;;; (progn (progn (something-with-side-effects) (yow)) +;;; (foo)) +;;; Further optimizations will turn (progn (list 1 2 3) 'foo) into 'foo. + +;;; I wonder if I missed any :-\) +(let ((side-effect-free-fns + '(% * + - / /= 1+ 1- < <= = > >= abs acos append aref ash asin atan + assoc assq + boundp buffer-file-name buffer-local-variables buffer-modified-p + buffer-substring + capitalize car-less-than-car car cdr ceiling concat + ;; coordinates-in-window-p not in XEmacs + copy-marker cos count-lines + default-boundp default-value documentation downcase + elt exp expt fboundp featurep + file-directory-p file-exists-p file-locked-p file-name-absolute-p + file-newer-than-file-p file-readable-p file-symlink-p file-writable-p + float floor format + get get-buffer get-buffer-window getenv get-file-buffer + int-to-string + length log log10 logand logb logior lognot logxor lsh + marker-buffer max member memq min mod + next-window nth nthcdr number-to-string + parse-colon-path previous-window + radians-to-degrees rassq regexp-quote reverse round + sin sqrt string< string= string-equal string-lessp string-to-char + string-to-int string-to-number substring symbol-plist + tan upcase user-variable-p vconcat + ;; XEmacs change: window-edges -> window-pixel-edges + window-buffer window-dedicated-p window-pixel-edges window-height + window-hscroll window-minibuffer-p window-width + zerop)) + (side-effect-and-error-free-fns + '(arrayp atom + bobp bolp buffer-end buffer-list buffer-size buffer-string bufferp + car-safe case-table-p cdr-safe char-or-string-p char-table-p + characterp commandp cons + consolep console-live-p consp + current-buffer + ;; XEmacs: extent functions, frame-live-p, various other stuff + devicep device-live-p + dot dot-marker eobp eolp eq eql equal eventp extentp + extent-live-p floatp framep frame-live-p + get-largest-window get-lru-window + identity ignore integerp integer-or-marker-p interactive-p + invocation-directory invocation-name + ;; keymapp may autoload in XEmacs, so not on this list! + list listp + make-marker mark mark-marker markerp memory-limit minibuffer-window + ;; mouse-movement-p not in XEmacs + natnump nlistp not null number-or-marker-p numberp + one-window-p ;; overlayp not in XEmacs + point point-marker point-min point-max processp + range-table-p + selected-window sequencep stringp subrp symbolp syntax-table-p + user-full-name user-login-name user-original-login-name + user-real-login-name user-real-uid user-uid + vector vectorp + window-configuration-p window-live-p windowp))) + (while side-effect-free-fns + (put (car side-effect-free-fns) 'side-effect-free t) + (setq side-effect-free-fns (cdr side-effect-free-fns))) + (while side-effect-and-error-free-fns + (put (car side-effect-and-error-free-fns) 'side-effect-free 'error-free) + (setq side-effect-and-error-free-fns (cdr side-effect-and-error-free-fns))) + nil) + + +(defun byte-compile-splice-in-already-compiled-code (form) + ;; form is (byte-code "..." [...] n) + (if (not (memq byte-optimize '(t lap))) + (byte-compile-normal-call form) + (byte-inline-lapcode + (byte-decompile-bytecode-1 (nth 1 form) (nth 2 form) t)) + (setq byte-compile-maxdepth (max (+ byte-compile-depth (nth 3 form)) + byte-compile-maxdepth)) + (setq byte-compile-depth (1+ byte-compile-depth)))) + +(put 'byte-code 'byte-compile 'byte-compile-splice-in-already-compiled-code) + + +(defconst byte-constref-ops + '(byte-constant byte-constant2 byte-varref byte-varset byte-varbind)) + +;;; This function extracts the bitfields from variable-length opcodes. +;;; Originally defined in disass.el (which no longer uses it.) + +(defun disassemble-offset () + "Don't call this!" + ;; fetch and return the offset for the current opcode. + ;; return NIL if this opcode has no offset + ;; OP, PTR and BYTES are used and set dynamically + (defvar op) + (defvar ptr) + (defvar bytes) + (cond ((< op byte-nth) + (let ((tem (logand op 7))) + (setq op (logand op 248)) + (cond ((eq tem 6) + (setq ptr (1+ ptr)) ;offset in next byte + ;; char-to-int to avoid downstream problems + ;; caused by chars appearing where ints are + ;; expected. In bytecode the bytes in the + ;; opcode string are always interpreted as ints. + (char-to-int (aref bytes ptr))) + ((eq tem 7) + (setq ptr (1+ ptr)) ;offset in next 2 bytes + (+ (aref bytes ptr) + (progn (setq ptr (1+ ptr)) + (lsh (aref bytes ptr) 8)))) + (t tem)))) ;offset was in opcode + ((>= op byte-constant) + (prog1 (- op byte-constant) ;offset in opcode + (setq op byte-constant))) + ((and (>= op byte-constant2) + (<= op byte-goto-if-not-nil-else-pop)) + (setq ptr (1+ ptr)) ;offset in next 2 bytes + (+ (aref bytes ptr) + (progn (setq ptr (1+ ptr)) + (lsh (aref bytes ptr) 8)))) + ;; XEmacs: this code was here before. FSF's first comparison + ;; is (>= op byte-listN). It appears that the rel-goto stuff + ;; does not exist in FSF 19.30. It doesn't exist in 19.28 + ;; either, so I'm going to assume that this is an improvement + ;; on our part and leave it in. --ben + ((and (>= op byte-rel-goto) + (<= op byte-insertN)) + (setq ptr (1+ ptr)) ;offset in next byte + ;; Use char-to-int to avoid downstream problems caused by + ;; chars appearing where ints are expected. In bytecode + ;; the bytes in the opcode string are always interpreted as + ;; ints. + (char-to-int (aref bytes ptr))))) + + +;;; This de-compiler is used for inline expansion of compiled functions, +;;; and by the disassembler. +;;; +;;; This list contains numbers, which are pc values, +;;; before each instruction. +(defun byte-decompile-bytecode (bytes constvec) + "Turns BYTECODE into lapcode, referring to CONSTVEC." + (let ((byte-compile-constants nil) + (byte-compile-variables nil) + (byte-compile-tag-number 0)) + (byte-decompile-bytecode-1 bytes constvec))) + +;; As byte-decompile-bytecode, but updates +;; byte-compile-{constants, variables, tag-number}. +;; If MAKE-SPLICEABLE is true, then `return' opcodes are replaced +;; with `goto's destined for the end of the code. +;; That is for use by the compiler. +;; If MAKE-SPLICEABLE is nil, we are being called for the disassembler. +;; In that case, we put a pc value into the list +;; before each insn (or its label). +(defun byte-decompile-bytecode-1 (bytes constvec &optional make-spliceable) + (let ((length (length bytes)) + (ptr 0) optr tags op offset + ;; tag unused + lap tmp + endtag + ;; (retcount 0) unused + ) + (while (not (= ptr length)) + (or make-spliceable + (setq lap (cons ptr lap))) + (setq op (aref bytes ptr) + optr ptr + offset (disassemble-offset)) ; this does dynamic-scope magic + (setq op (aref byte-code-vector op)) + ;; XEmacs: the next line in FSF 19.30 reads + ;; (cond ((memq op byte-goto-ops) + ;; see the comment above about byte-rel-goto in XEmacs. + (cond ((or (memq op byte-goto-ops) + (cond ((memq op byte-rel-goto-ops) + (setq op (aref byte-code-vector + (- (symbol-value op) + (- byte-rel-goto byte-goto)))) + (setq offset (+ ptr (- offset 127))) + t))) + ;; it's a pc + (setq offset + (cdr (or (assq offset tags) + (car (setq tags + (cons (cons offset + (byte-compile-make-tag)) + tags))))))) + ((cond ((eq op 'byte-constant2) (setq op 'byte-constant) t) + ((memq op byte-constref-ops))) + (setq tmp (aref constvec offset) + offset (if (eq op 'byte-constant) + (byte-compile-get-constant tmp) + (or (assq tmp byte-compile-variables) + (car (setq byte-compile-variables + (cons (list tmp) + byte-compile-variables))))))) + ((and make-spliceable + (eq op 'byte-return)) + (if (= ptr (1- length)) + (setq op nil) + (setq offset (or endtag (setq endtag (byte-compile-make-tag))) + op 'byte-goto)))) + ;; lap = ( [ (pc . (op . arg)) ]* ) + (setq lap (cons (cons optr (cons op (or offset 0))) + lap)) + (setq ptr (1+ ptr))) + ;; take off the dummy nil op that we replaced a trailing "return" with. + (let ((rest lap)) + (while rest + (cond ((numberp (car rest))) + ((setq tmp (assq (car (car rest)) tags)) + ;; this addr is jumped to + (setcdr rest (cons (cons nil (cdr tmp)) + (cdr rest))) + (setq tags (delq tmp tags)) + (setq rest (cdr rest)))) + (setq rest (cdr rest)))) + (if tags (error "optimizer error: missed tags %s" tags)) + (if (null (car (cdr (car lap)))) + (setq lap (cdr lap))) + (if endtag + (setq lap (cons (cons nil endtag) lap))) + ;; remove addrs, lap = ( [ (op . arg) | (TAG tagno) ]* ) + (mapcar (function (lambda (elt) + (if (numberp elt) + elt + (cdr elt)))) + (nreverse lap)))) + + +;;; peephole optimizer + +(defconst byte-tagref-ops (cons 'TAG byte-goto-ops)) + +(defconst byte-conditional-ops + '(byte-goto-if-nil byte-goto-if-not-nil byte-goto-if-nil-else-pop + byte-goto-if-not-nil-else-pop)) + +(defconst byte-after-unbind-ops + '(byte-constant byte-dup + byte-symbolp byte-consp byte-stringp byte-listp byte-numberp byte-integerp + byte-eq byte-equal byte-not + byte-cons byte-list1 byte-list2 ; byte-list3 byte-list4 + byte-interactive-p) + ;; How about other side-effect-free-ops? Is it safe to move an + ;; error invocation (such as from nth) out of an unwind-protect? + "Byte-codes that can be moved past an unbind.") + +(defconst byte-compile-side-effect-and-error-free-ops + '(byte-constant byte-dup byte-symbolp byte-consp byte-stringp byte-listp + byte-integerp byte-numberp byte-eq byte-equal byte-not byte-car-safe + byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max + byte-point-min byte-following-char byte-preceding-char + byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp + byte-current-buffer byte-interactive-p)) + +(defconst byte-compile-side-effect-free-ops + (nconc + '(byte-varref byte-nth byte-memq byte-car byte-cdr byte-length byte-aref + byte-symbol-value byte-get byte-concat2 byte-concat3 byte-sub1 byte-add1 + byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate + byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax + byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt + byte-member byte-assq byte-quo byte-rem) + byte-compile-side-effect-and-error-free-ops)) + +;;; This piece of shit is because of the way DEFVAR_BOOL() variables work. +;;; Consider the code +;;; +;;; (defun foo (flag) +;;; (let ((old-pop-ups pop-up-windows) +;;; (pop-up-windows flag)) +;;; (cond ((not (eq pop-up-windows old-pop-ups)) +;;; (setq old-pop-ups pop-up-windows) +;;; ...)))) +;;; +;;; Uncompiled, old-pop-ups will always be set to nil or t, even if FLAG is +;;; something else. But if we optimize +;;; +;;; varref flag +;;; varbind pop-up-windows +;;; varref pop-up-windows +;;; not +;;; to +;;; varref flag +;;; dup +;;; varbind pop-up-windows +;;; not +;;; +;;; we break the program, because it will appear that pop-up-windows and +;;; old-pop-ups are not EQ when really they are. So we have to know what +;;; the BOOL variables are, and not perform this optimization on them. +;;; +(defconst byte-boolean-vars + '(abbrev-all-caps purify-flag find-file-compare-truenames + find-file-use-truenames find-file-visit-truename + find-file-existing-other-name byte-metering-on + zmacs-regions zmacs-region-active-p zmacs-region-stays + atomic-extent-goto-char-p suppress-early-error-handler + noninteractive ignore-kernel debug-on-quit debug-on-next-call + modifier-keys-are-sticky x-allow-sendevents vms-stmlf-recfm + disable-auto-save-when-buffer-shrinks indent-tabs-mode + load-in-progress load-warn-when-source-newer load-warn-when-source-only + load-ignore-elc-files load-force-doc-strings + fail-on-bucky-bit-character-escapes popup-menu-titles + menubar-show-keybindings completion-ignore-case + canna-empty-info canna-through-info canna-underline + canna-inhibit-hankakukana x-handle-non-fully-specified-fonts + print-escape-newlines print-readably print-gensym + delete-exited-processes truncate-partial-width-windows + visible-bell no-redraw-on-reenter cursor-in-echo-area + inhibit-warning-display parse-sexp-ignore-comments words-include-escapes + scroll-on-clipped-lines pop-up-frames pop-up-windows) + "DEFVAR_BOOL variables. Giving these any non-nil value sets them to t. +If this does not enumerate all DEFVAR_BOOL variables, the byte-optimizer +may generate incorrect code.") + +(defun byte-optimize-lapcode (lap &optional for-effect) + "Simple peephole optimizer. LAP is both modified and returned." + (let (lap0 ;; off0 unused + lap1 ;; off1 + lap2 ;; off2 + (keep-going 'first-time) + (add-depth 0) + rest tmp tmp2 tmp3 + (side-effect-free (if byte-compile-delete-errors + byte-compile-side-effect-free-ops + byte-compile-side-effect-and-error-free-ops))) + (while keep-going + (or (eq keep-going 'first-time) + (byte-compile-log-lap " ---- next pass")) + (setq rest lap + keep-going nil) + (while rest + (setq lap0 (car rest) + lap1 (nth 1 rest) + lap2 (nth 2 rest)) + + ;; You may notice that sequences like "dup varset discard" are + ;; optimized but sequences like "dup varset TAG1: discard" are not. + ;; You may be tempted to change this; resist that temptation. + (cond ;; + ;; pop --> + ;; ...including: + ;; const-X pop --> + ;; varref-X pop --> + ;; dup pop --> + ;; + ((and (eq 'byte-discard (car lap1)) + (memq (car lap0) side-effect-free)) + (setq keep-going t) + (setq tmp (aref byte-stack+-info (symbol-value (car lap0)))) + (setq rest (cdr rest)) + (cond ((= tmp 1) + (byte-compile-log-lap + " %s discard\t-->\t" lap0) + (setq lap (delq lap0 (delq lap1 lap)))) + ((= tmp 0) + (byte-compile-log-lap + " %s discard\t-->\t discard" lap0) + (setq lap (delq lap0 lap))) + ((= tmp -1) + (byte-compile-log-lap + " %s discard\t-->\tdiscard discard" lap0) + (setcar lap0 'byte-discard) + (setcdr lap0 0)) + ((error "Optimizer error: too much on the stack")))) + ;; + ;; goto*-X X: --> X: + ;; + ((and (memq (car lap0) byte-goto-ops) + (eq (cdr lap0) lap1)) + (cond ((eq (car lap0) 'byte-goto) + (setq lap (delq lap0 lap)) + (setq tmp "")) + ((memq (car lap0) byte-goto-always-pop-ops) + (setcar lap0 (setq tmp 'byte-discard)) + (setcdr lap0 0)) + ((error "Depth conflict at tag %d" (nth 2 lap0)))) + (and (memq byte-optimize-log '(t byte)) + (byte-compile-log " (goto %s) %s:\t-->\t%s %s:" + (nth 1 lap1) (nth 1 lap1) + tmp (nth 1 lap1))) + (setq keep-going t)) + ;; + ;; varset-X varref-X --> dup varset-X + ;; varbind-X varref-X --> dup varbind-X + ;; const/dup varset-X varref-X --> const/dup varset-X const/dup + ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup + ;; The latter two can enable other optimizations. + ;; + ((and (eq 'byte-varref (car lap2)) + (eq (cdr lap1) (cdr lap2)) + (memq (car lap1) '(byte-varset byte-varbind))) + (if (and (setq tmp (memq (car (cdr lap2)) byte-boolean-vars)) + (not (eq (car lap0) 'byte-constant))) + nil + (setq keep-going t) + (if (memq (car lap0) '(byte-constant byte-dup)) + (progn + (setq tmp (if (or (not tmp) + (memq (car (cdr lap0)) '(nil t))) + (cdr lap0) + (byte-compile-get-constant t))) + (byte-compile-log-lap " %s %s %s\t-->\t%s %s %s" + lap0 lap1 lap2 lap0 lap1 + (cons (car lap0) tmp)) + (setcar lap2 (car lap0)) + (setcdr lap2 tmp)) + (byte-compile-log-lap " %s %s\t-->\tdup %s" lap1 lap2 lap1) + (setcar lap2 (car lap1)) + (setcar lap1 'byte-dup) + (setcdr lap1 0) + ;; The stack depth gets locally increased, so we will + ;; increase maxdepth in case depth = maxdepth here. + ;; This can cause the third argument to byte-code to + ;; be larger than necessary. + (setq add-depth 1)))) + ;; + ;; dup varset-X discard --> varset-X + ;; dup varbind-X discard --> varbind-X + ;; (the varbind variant can emerge from other optimizations) + ;; + ((and (eq 'byte-dup (car lap0)) + (eq 'byte-discard (car lap2)) + (memq (car lap1) '(byte-varset byte-varbind))) + (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1) + (setq keep-going t + rest (cdr rest)) + (setq lap (delq lap0 (delq lap2 lap)))) + ;; + ;; not goto-X-if-nil --> goto-X-if-non-nil + ;; not goto-X-if-non-nil --> goto-X-if-nil + ;; + ;; it is wrong to do the same thing for the -else-pop variants. + ;; + ((and (eq 'byte-not (car lap0)) + (or (eq 'byte-goto-if-nil (car lap1)) + (eq 'byte-goto-if-not-nil (car lap1)))) + (byte-compile-log-lap " not %s\t-->\t%s" + lap1 + (cons + (if (eq (car lap1) 'byte-goto-if-nil) + 'byte-goto-if-not-nil + 'byte-goto-if-nil) + (cdr lap1))) + (setcar lap1 (if (eq (car lap1) 'byte-goto-if-nil) + 'byte-goto-if-not-nil + 'byte-goto-if-nil)) + (setq lap (delq lap0 lap)) + (setq keep-going t)) + ;; + ;; goto-X-if-nil goto-Y X: --> goto-Y-if-non-nil X: + ;; goto-X-if-non-nil goto-Y X: --> goto-Y-if-nil X: + ;; + ;; it is wrong to do the same thing for the -else-pop variants. + ;; + ((and (or (eq 'byte-goto-if-nil (car lap0)) + (eq 'byte-goto-if-not-nil (car lap0))) ; gotoX + (eq 'byte-goto (car lap1)) ; gotoY + (eq (cdr lap0) lap2)) ; TAG X + (let ((inverse (if (eq 'byte-goto-if-nil (car lap0)) + 'byte-goto-if-not-nil 'byte-goto-if-nil))) + (byte-compile-log-lap " %s %s %s:\t-->\t%s %s:" + lap0 lap1 lap2 + (cons inverse (cdr lap1)) lap2) + (setq lap (delq lap0 lap)) + (setcar lap1 inverse) + (setq keep-going t))) + ;; + ;; const goto-if-* --> whatever + ;; + ((and (eq 'byte-constant (car lap0)) + (memq (car lap1) byte-conditional-ops)) + (cond ((if (or (eq (car lap1) 'byte-goto-if-nil) + (eq (car lap1) 'byte-goto-if-nil-else-pop)) + (car (cdr lap0)) + (not (car (cdr lap0)))) + (byte-compile-log-lap " %s %s\t-->\t" + lap0 lap1) + (setq rest (cdr rest) + lap (delq lap0 (delq lap1 lap)))) + (t + (if (memq (car lap1) byte-goto-always-pop-ops) + (progn + (byte-compile-log-lap " %s %s\t-->\t%s" + lap0 lap1 (cons 'byte-goto (cdr lap1))) + (setq lap (delq lap0 lap))) + (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 + (cons 'byte-goto (cdr lap1)))) + (setcar lap1 'byte-goto))) + (setq keep-going t)) + ;; + ;; varref-X varref-X --> varref-X dup + ;; varref-X [dup ...] varref-X --> varref-X [dup ...] dup + ;; We don't optimize the const-X variations on this here, + ;; because that would inhibit some goto optimizations; we + ;; optimize the const-X case after all other optimizations. + ;; + ((and (eq 'byte-varref (car lap0)) + (progn + (setq tmp (cdr rest)) + (while (eq (car (car tmp)) 'byte-dup) + (setq tmp (cdr tmp))) + t) + (eq (cdr lap0) (cdr (car tmp))) + (eq 'byte-varref (car (car tmp)))) + (if (memq byte-optimize-log '(t byte)) + (let ((str "")) + (setq tmp2 (cdr rest)) + (while (not (eq tmp tmp2)) + (setq tmp2 (cdr tmp2) + str (concat str " dup"))) + (byte-compile-log-lap " %s%s %s\t-->\t%s%s dup" + lap0 str lap0 lap0 str))) + (setq keep-going t) + (setcar (car tmp) 'byte-dup) + (setcdr (car tmp) 0) + (setq rest tmp)) + ;; + ;; TAG1: TAG2: --> TAG1: + ;; (and other references to TAG2 are replaced with TAG1) + ;; + ((and (eq (car lap0) 'TAG) + (eq (car lap1) 'TAG)) + (and (memq byte-optimize-log '(t byte)) + (byte-compile-log " adjacent tags %d and %d merged" + (nth 1 lap1) (nth 1 lap0))) + (setq tmp3 lap) + (while (setq tmp2 (rassq lap0 tmp3)) + (setcdr tmp2 lap1) + (setq tmp3 (cdr (memq tmp2 tmp3)))) + (setq lap (delq lap0 lap) + keep-going t)) + ;; + ;; unused-TAG: --> + ;; + ((and (eq 'TAG (car lap0)) + (not (rassq lap0 lap))) + (and (memq byte-optimize-log '(t byte)) + (byte-compile-log " unused tag %d removed" (nth 1 lap0))) + (setq lap (delq lap0 lap) + keep-going t)) + ;; + ;; goto ... --> goto + ;; return ... --> return + ;; + ((and (memq (car lap0) '(byte-goto byte-return)) + (not (memq (car lap1) '(TAG nil)))) + (setq tmp rest) + (let ((i 0) + (opt-p (memq byte-optimize-log '(t lap))) + str deleted) + (while (and (setq tmp (cdr tmp)) + (not (eq 'TAG (car (car tmp))))) + (if opt-p (setq deleted (cons (car tmp) deleted) + str (concat str " %s") + i (1+ i)))) + (if opt-p + (let ((tagstr + (if (eq 'TAG (car (car tmp))) + (format "%d:" (car (cdr (car tmp)))) + (or (car tmp) "")))) + (if (< i 6) + (apply 'byte-compile-log-lap-1 + (concat " %s" str + " %s\t-->\t%s %s") + lap0 + (nconc (nreverse deleted) + (list tagstr lap0 tagstr))) + (byte-compile-log-lap + " %s <%d unreachable op%s> %s\t-->\t%s %s" + lap0 i (if (= i 1) "" "s") + tagstr lap0 tagstr)))) + (rplacd rest tmp)) + (setq keep-going t)) + ;; + ;; unbind --> unbind + ;; (this may enable other optimizations.) + ;; + ((and (eq 'byte-unbind (car lap1)) + (memq (car lap0) byte-after-unbind-ops)) + (byte-compile-log-lap " %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0) + (setcar rest lap1) + (setcar (cdr rest) lap0) + (setq keep-going t)) + ;; + ;; varbind-X unbind-N --> discard unbind-(N-1) + ;; save-excursion unbind-N --> unbind-(N-1) + ;; save-restriction unbind-N --> unbind-(N-1) + ;; + ((and (eq 'byte-unbind (car lap1)) + (memq (car lap0) '(byte-varbind byte-save-excursion + byte-save-restriction)) + (< 0 (cdr lap1))) + (if (zerop (setcdr lap1 (1- (cdr lap1)))) + (delq lap1 rest)) + (if (eq (car lap0) 'byte-varbind) + (setcar rest (cons 'byte-discard 0)) + (setq lap (delq lap0 lap))) + (byte-compile-log-lap " %s %s\t-->\t%s %s" + lap0 (cons (car lap1) (1+ (cdr lap1))) + (if (eq (car lap0) 'byte-varbind) + (car rest) + (car (cdr rest))) + (if (and (/= 0 (cdr lap1)) + (eq (car lap0) 'byte-varbind)) + (car (cdr rest)) + "")) + (setq keep-going t)) + ;; + ;; goto*-X ... X: goto-Y --> goto*-Y + ;; goto-X ... X: return --> return + ;; + ((and (memq (car lap0) byte-goto-ops) + (memq (car (setq tmp (nth 1 (memq (cdr lap0) lap)))) + '(byte-goto byte-return))) + (cond ((and (not (eq tmp lap0)) + (or (eq (car lap0) 'byte-goto) + (eq (car tmp) 'byte-goto))) + (byte-compile-log-lap " %s [%s]\t-->\t%s" + (car lap0) tmp tmp) + (if (eq (car tmp) 'byte-return) + (setcar lap0 'byte-return)) + (setcdr lap0 (cdr tmp)) + (setq keep-going t)))) + ;; + ;; goto-*-else-pop X ... X: goto-if-* --> whatever + ;; goto-*-else-pop X ... X: discard --> whatever + ;; + ((and (memq (car lap0) '(byte-goto-if-nil-else-pop + byte-goto-if-not-nil-else-pop)) + (memq (car (car (setq tmp (cdr (memq (cdr lap0) lap))))) + (eval-when-compile + (cons 'byte-discard byte-conditional-ops))) + (not (eq lap0 (car tmp)))) + (setq tmp2 (car tmp)) + (setq tmp3 (assq (car lap0) '((byte-goto-if-nil-else-pop + byte-goto-if-nil) + (byte-goto-if-not-nil-else-pop + byte-goto-if-not-nil)))) + (if (memq (car tmp2) tmp3) + (progn (setcar lap0 (car tmp2)) + (setcdr lap0 (cdr tmp2)) + (byte-compile-log-lap " %s-else-pop [%s]\t-->\t%s" + (car lap0) tmp2 lap0)) + ;; Get rid of the -else-pop's and jump one step further. + (or (eq 'TAG (car (nth 1 tmp))) + (setcdr tmp (cons (byte-compile-make-tag) + (cdr tmp)))) + (byte-compile-log-lap " %s [%s]\t-->\t%s " + (car lap0) tmp2 (nth 1 tmp3)) + (setcar lap0 (nth 1 tmp3)) + (setcdr lap0 (nth 1 tmp))) + (setq keep-going t)) + ;; + ;; const goto-X ... X: goto-if-* --> whatever + ;; const goto-X ... X: discard --> whatever + ;; + ((and (eq (car lap0) 'byte-constant) + (eq (car lap1) 'byte-goto) + (memq (car (car (setq tmp (cdr (memq (cdr lap1) lap))))) + (eval-when-compile + (cons 'byte-discard byte-conditional-ops))) + (not (eq lap1 (car tmp)))) + (setq tmp2 (car tmp)) + (cond ((memq (car tmp2) + (if (null (car (cdr lap0))) + '(byte-goto-if-nil byte-goto-if-nil-else-pop) + '(byte-goto-if-not-nil + byte-goto-if-not-nil-else-pop))) + (byte-compile-log-lap " %s goto [%s]\t-->\t%s %s" + lap0 tmp2 lap0 tmp2) + (setcar lap1 (car tmp2)) + (setcdr lap1 (cdr tmp2)) + ;; Let next step fix the (const,goto-if*) sequence. + (setq rest (cons nil rest))) + (t + ;; Jump one step further + (byte-compile-log-lap + " %s goto [%s]\t-->\t goto " + lap0 tmp2) + (or (eq 'TAG (car (nth 1 tmp))) + (setcdr tmp (cons (byte-compile-make-tag) + (cdr tmp)))) + (setcdr lap1 (car (cdr tmp))) + (setq lap (delq lap0 lap)))) + (setq keep-going t)) + ;; + ;; X: varref-Y ... varset-Y goto-X --> + ;; X: varref-Y Z: ... dup varset-Y goto-Z + ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.) + ;; (This is so usual for while loops that it is worth handling). + ;; + ((and (eq (car lap1) 'byte-varset) + (eq (car lap2) 'byte-goto) + (not (memq (cdr lap2) rest)) ;Backwards jump + (eq (car (car (setq tmp (cdr (memq (cdr lap2) lap))))) + 'byte-varref) + (eq (cdr (car tmp)) (cdr lap1)) + (not (memq (car (cdr lap1)) byte-boolean-vars))) + ;;(byte-compile-log-lap " Pulled %s to end of loop" (car tmp)) + (let ((newtag (byte-compile-make-tag))) + (byte-compile-log-lap + " %s: %s ... %s %s\t-->\t%s: %s %s: ... %s %s %s" + (nth 1 (cdr lap2)) (car tmp) + lap1 lap2 + (nth 1 (cdr lap2)) (car tmp) + (nth 1 newtag) 'byte-dup lap1 + (cons 'byte-goto newtag) + ) + (setcdr rest (cons (cons 'byte-dup 0) (cdr rest))) + (setcdr tmp (cons (setcdr lap2 newtag) (cdr tmp)))) + (setq add-depth 1) + (setq keep-going t)) + ;; + ;; goto-X Y: ... X: goto-if*-Y --> goto-if-not-*-X+1 Y: + ;; (This can pull the loop test to the end of the loop) + ;; + ((and (eq (car lap0) 'byte-goto) + (eq (car lap1) 'TAG) + (eq lap1 + (cdr (car (setq tmp (cdr (memq (cdr lap0) lap)))))) + (memq (car (car tmp)) + '(byte-goto byte-goto-if-nil byte-goto-if-not-nil + byte-goto-if-nil-else-pop))) +;; (byte-compile-log-lap " %s %s, %s %s --> moved conditional" +;; lap0 lap1 (cdr lap0) (car tmp)) + (let ((newtag (byte-compile-make-tag))) + (byte-compile-log-lap + "%s %s: ... %s: %s\t-->\t%s ... %s:" + lap0 (nth 1 lap1) (nth 1 (cdr lap0)) (car tmp) + (cons (cdr (assq (car (car tmp)) + '((byte-goto-if-nil . byte-goto-if-not-nil) + (byte-goto-if-not-nil . byte-goto-if-nil) + (byte-goto-if-nil-else-pop . + byte-goto-if-not-nil-else-pop) + (byte-goto-if-not-nil-else-pop . + byte-goto-if-nil-else-pop)))) + newtag) + + (nth 1 newtag) + ) + (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp))) + (if (eq (car (car tmp)) 'byte-goto-if-nil-else-pop) + ;; We can handle this case but not the -if-not-nil case, + ;; because we won't know which non-nil constant to push. + (setcdr rest (cons (cons 'byte-constant + (byte-compile-get-constant nil)) + (cdr rest)))) + (setcar lap0 (nth 1 (memq (car (car tmp)) + '(byte-goto-if-nil-else-pop + byte-goto-if-not-nil + byte-goto-if-nil + byte-goto-if-not-nil + byte-goto byte-goto)))) + ) + (setq keep-going t)) + ) + (setq rest (cdr rest))) + ) + ;; Cleanup stage: + ;; Rebuild byte-compile-constants / byte-compile-variables. + ;; Simple optimizations that would inhibit other optimizations if they + ;; were done in the optimizing loop, and optimizations which there is no + ;; need to do more than once. + (setq byte-compile-constants nil + byte-compile-variables nil) + (setq rest lap) + (while rest + (setq lap0 (car rest) + lap1 (nth 1 rest)) + (if (memq (car lap0) byte-constref-ops) + (if (eq (cdr lap0) 'byte-constant) + (or (memq (cdr lap0) byte-compile-variables) + (setq byte-compile-variables (cons (cdr lap0) + byte-compile-variables))) + (or (memq (cdr lap0) byte-compile-constants) + (setq byte-compile-constants (cons (cdr lap0) + byte-compile-constants))))) + (cond (;; + ;; const-C varset-X const-C --> const-C dup varset-X + ;; const-C varbind-X const-C --> const-C dup varbind-X + ;; + (and (eq (car lap0) 'byte-constant) + (eq (car (nth 2 rest)) 'byte-constant) + (eq (cdr lap0) (car (nth 2 rest))) + (memq (car lap1) '(byte-varbind byte-varset))) + (byte-compile-log-lap " %s %s %s\t-->\t%s dup %s" + lap0 lap1 lap0 lap0 lap1) + (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1))) + (setcar (cdr rest) (cons 'byte-dup 0)) + (setq add-depth 1)) + ;; + ;; const-X [dup/const-X ...] --> const-X [dup ...] dup + ;; varref-X [dup/varref-X ...] --> varref-X [dup ...] dup + ;; + ((memq (car lap0) '(byte-constant byte-varref)) + (setq tmp rest + tmp2 nil) + (while (progn + (while (eq 'byte-dup (car (car (setq tmp (cdr tmp)))))) + (and (eq (cdr lap0) (cdr (car tmp))) + (eq (car lap0) (car (car tmp))))) + (setcar tmp (cons 'byte-dup 0)) + (setq tmp2 t)) + (if tmp2 + (byte-compile-log-lap + " %s [dup/%s]...\t-->\t%s dup..." lap0 lap0 lap0))) + ;; + ;; unbind-N unbind-M --> unbind-(N+M) + ;; + ((and (eq 'byte-unbind (car lap0)) + (eq 'byte-unbind (car lap1))) + (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 + (cons 'byte-unbind + (+ (cdr lap0) (cdr lap1)))) + (setq keep-going t) + (setq lap (delq lap0 lap)) + (setcdr lap1 (+ (cdr lap1) (cdr lap0)))) + ) + (setq rest (cdr rest))) + (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) + lap) + +(provide 'byte-optimize) + + +;; To avoid "lisp nesting exceeds max-lisp-eval-depth" when this file compiles +;; itself, compile some of its most used recursive functions (at load time). +;; +(eval-when-compile + (or (compiled-function-p (symbol-function 'byte-optimize-form)) + (assq 'byte-code (symbol-function 'byte-optimize-form)) + (let ((byte-optimize nil) + (byte-compile-warnings nil)) + (mapcar '(lambda (x) + (or noninteractive (message "compiling %s..." x)) + (byte-compile x) + (or noninteractive (message "compiling %s...done" x))) + '(byte-optimize-form + byte-optimize-body + byte-optimize-predicate + byte-optimize-binary-predicate + ;; Inserted some more than necessary, to speed it up. + byte-optimize-form-code-walker + byte-optimize-lapcode)))) + nil) + +;;; byte-optimize.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp-runtime.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/bytecomp-runtime.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,241 @@ +;;; bytecomp-runtime.el --- byte-compiler support for inlining + +;; Copyright (C) 1992, 1997 Free Software Foundation, Inc. + +;; Author: Jamie Zawinski +;; Author: Hallvard Furuseth +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; The code in this file should always be loaded, because it defines things +;; like "defsubst" which should work interpreted as well. The code in +;; bytecomp.el and byte-optimize.el can be loaded as needed. + +;; interface to selectively inlining functions. +;; This only happens when source-code optimization is turned on. + +;;; Code: + +;; Redefined in byte-optimize.el. +;; This is not documented--it's not clear that we should promote it. +(fset 'inline 'progn) +(put 'inline 'lisp-indent-hook 0) + + +;;; Interface to inline functions. + +;; FSF comments the next two out, but I see no reason to do so. --ben +(defmacro proclaim-inline (&rest fns) + "Cause the named functions to be open-coded when called from compiled code. +They will only be compiled open-coded when byte-optimize is true." + (cons 'eval-and-compile + (apply + 'nconc + (mapcar + '(lambda (x) + (` ((or (memq (get '(, x) 'byte-optimizer) + '(nil byte-compile-inline-expand)) + (error + "%s already has a byte-optimizer, can't make it inline" + '(, x))) + (put '(, x) 'byte-optimizer 'byte-compile-inline-expand)))) + fns)))) + + +(defmacro proclaim-notinline (&rest fns) + "Cause the named functions to no longer be open-coded." + (cons 'eval-and-compile + (apply + 'nconc + (mapcar + '(lambda (x) + (` ((if (eq (get '(, x) 'byte-optimizer) + 'byte-compile-inline-expand) + (put '(, x) 'byte-optimizer nil))))) + fns)))) + +;; This has a special byte-hunk-handler in bytecomp.el. +(defmacro defsubst (name arglist &rest body) + "Define an inline function. The syntax is just like that of `defun'." + (or (memq (get name 'byte-optimizer) + '(nil byte-compile-inline-expand)) + (error "`%s' is a primitive" name)) + (list 'prog1 + (cons 'defun (cons name (cons arglist body))) + (list 'proclaim-inline name))) +; Instead of the above line, FSF has this: +; (list 'eval-and-compile +; (list 'put (list 'quote name) +; ''byte-optimizer ''byte-compile-inline-expand)))) + +(defun make-obsolete (fn new) + "Make the byte-compiler warn that FUNCTION is obsolete. +The warning will say that NEW should be used instead. +If NEW is a string, that is the `use instead' message." + (interactive "aMake function obsolete: \nxObsoletion replacement: ") + (let ((handler (get fn 'byte-compile))) + (if (eq 'byte-compile-obsolete handler) + (setcar (get fn 'byte-obsolete-info) new) + (put fn 'byte-obsolete-info (cons new handler)) + (put fn 'byte-compile 'byte-compile-obsolete))) + fn) + +(defun make-obsolete-variable (var new) + "Make the byte-compiler warn that VARIABLE is obsolete, +and NEW should be used instead. If NEW is a string, then that is the +`use instead' message." + (interactive + (list + (let ((str (completing-read "Make variable obsolete: " obarray 'boundp t))) + (if (equal str "") (error "")) + (intern str)) + (car (read-from-string (read-string "Obsoletion replacement: "))))) + (put var 'byte-obsolete-variable new) + var) + +;; By overwhelming demand, we separate out truly obsolete symbols from +;; those that are present for GNU Emacs compatibility. +(defun make-compatible (fn new) + "Make the byte-compiler know that FUNCTION is provided for compatibility. +The warning will say that NEW should be used instead. +If NEW is a string, that is the `use instead' message." + (interactive "aMake function compatible: \nxCompatible replacement: ") + (let ((handler (get fn 'byte-compile))) + (if (eq 'byte-compile-compatible handler) + (setcar (get fn 'byte-compatible-info) new) + (put fn 'byte-compatible-info (cons new handler)) + (put fn 'byte-compile 'byte-compile-compatible))) + fn) + +(defun make-compatible-variable (var new) + "Make the byte-compiler know that VARIABLE is provided for compatibility. +and NEW should be used instead. If NEW is a string, then that is the +`use instead' message." + (interactive + (list + (let ((str (completing-read "Make variable compatible: " + obarray 'boundp t))) + (if (equal str "") (error "")) + (intern str)) + (car (read-from-string (read-string "Compatible replacement: "))))) + (put var 'byte-compatible-variable new) + var) + +(put 'dont-compile 'lisp-indent-hook 0) +(defmacro dont-compile (&rest body) + "Like `progn', but the body always runs interpreted (not compiled). +If you think you need this, you're probably making a mistake somewhere." + (list 'eval (list 'quote (if (cdr body) (cons 'progn body) (car body))))) + + +;;; interface to evaluating things at compile time and/or load time +;;; these macro must come after any uses of them in this file, as their +;;; definition in the file overrides the magic definitions on the +;;; byte-compile-macro-environment. + +(put 'eval-when-compile 'lisp-indent-hook 0) +(defmacro eval-when-compile (&rest body) + "Like `progn', but evaluates the body at compile time. +The result of the body appears to the compiler as a quoted constant." + ;; Not necessary because we have it in b-c-initial-macro-environment + ;; (list 'quote (eval (cons 'progn body))) + (cons 'progn body)) + +(put 'eval-and-compile 'lisp-indent-hook 0) +(defmacro eval-and-compile (&rest body) + "Like `progn', but evaluates the body at compile time and at load time." + ;; Remember, it's magic. + (cons 'progn body)) + +;;; From Emacs 20. +(put 'eval-when-feature 'lisp-indent-hook 1) +(defmacro eval-when-feature (feature &rest body) + "Run the body forms when FEATURE is featurep, be it now or later. +Called (eval-when-feature (FEATURE [. FILENAME]) BODYFORMS...). +If (featurep 'FEATURE), evals now; otherwise adds an elt to +`after-load-alist' (which see), using FEATURE as filename if FILENAME is nil." + (let ((file (or (cdr feature) (symbol-name (car feature))))) + `(let ((bodythunk (function (lambda () ,@body)))) + (if (featurep ',(car feature)) + (funcall bodythunk) + (setq after-load-alist (cons '(,file . (list 'lambda '() bodythunk)) + after-load-alist)))))) + + + +;;; Interface to file-local byte-compiler parameters. +;;; Redefined in bytecomp.el. + +;;; The great RMS speaketh: +;;; +;;; I nuked this because it's not a good idea for users to think of +;;; using it. These options are a matter of installation preference, +;;; and have nothing to do with particular source files; it's a +;;; mistake to suggest to users that they should associate these with +;;; particular source files. There is hardly any reason to change +;;; these parameters, anyway. --rms. +;;; +;;; But I'll leave this stuff alone. --ben + +(put 'byte-compiler-options 'lisp-indent-hook 0) +(defmacro byte-compiler-options (&rest args) + "Set some compilation-parameters for this file. +This will affect only the file in which it appears; this does nothing when +evaluated, or when loaded from a .el file. + +Each argument to this macro must be a list of a key and a value. + + Keys: Values: Corresponding variable: + + verbose t, nil byte-compile-verbose + optimize t, nil, source, byte byte-optimize + warnings list of warnings byte-compile-warnings + file-format emacs19, emacs20 byte-compile-emacs19-compatibility + +The value specified with the `warnings' option must be a list, containing +some subset of the following flags: + + free-vars references to variables not in the current lexical scope. + unused-vars references to non-global variables bound but not referenced. + unresolved calls to unknown functions. + callargs lambda calls with args that don't match the definition. + redefine function cell redefined from a macro to a lambda or vice + versa, or redefined to take a different number of arguments. + +If the first element if the list is `+' or `-' then the specified elements +are added to or removed from the current set of warnings, instead of the +entire set of warnings being overwritten. + +For example, something like this might appear at the top of a source file: + + (byte-compiler-options + (optimize t) + (warnings (- callargs)) ; Don't warn about arglist mismatch + (warnings (+ unused-vars)) ; Do warn about unused bindings + (file-format emacs19))" + nil) + +;;; bytecomp-runtime.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/bytecomp.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,4100 @@ +;;; bytecomp.el --- compilation of Lisp code into byte code. + +;;; Copyright (C) 1985-1987, 1991-1994 Free Software Foundation, Inc. +;;; Copyright (C) 1996 Ben Wing. + +;; Author: Jamie Zawinski +;; Hallvard Furuseth +;; Keywords: internal + +;; Subsequently modified by RMS and others. + +(defconst byte-compile-version (purecopy "2.25 XEmacs; 22-Mar-96.")) + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30. + +;;; Commentary: + +;; The Emacs Lisp byte compiler. This crunches lisp source into a sort +;; of p-code which takes up less space and can be interpreted faster. +;; The user entry points are byte-compile-file and byte-recompile-directory. + +;;; Code: + +;;; ======================================================================== +;;; Entry points: +;;; byte-recompile-directory, byte-compile-file, +;;; batch-byte-compile, batch-byte-recompile-directory, +;;; byte-compile, compile-defun, +;;; display-call-tree +;;; RMS says: +;;; (byte-compile-buffer and byte-compile-and-load-file were turned off +;;; because they are not terribly useful and get in the way of completion.) +;;; But I'm leaving them. --ben + +;;; This version of the byte compiler has the following improvements: +;;; + optimization of compiled code: +;;; - removal of unreachable code; +;;; - removal of calls to side-effectless functions whose return-value +;;; is unused; +;;; - compile-time evaluation of safe constant forms, such as (consp nil) +;;; and (ash 1 6); +;;; - open-coding of literal lambdas; +;;; - peephole optimization of emitted code; +;;; - trivial functions are left uncompiled for speed. +;;; + support for inline functions; +;;; + compile-time evaluation of arbitrary expressions; +;;; + compile-time warning messages for: +;;; - functions being redefined with incompatible arglists; +;;; - functions being redefined as macros, or vice-versa; +;;; - functions or macros defined multiple times in the same file; +;;; - functions being called with the incorrect number of arguments; +;;; - functions being called which are not defined globally, in the +;;; file, or as autoloads; +;;; - assignment and reference of undeclared free variables; +;;; - various syntax errors; +;;; + correct compilation of nested defuns, defmacros, defvars and defsubsts; +;;; + correct compilation of top-level uses of macros; +;;; + the ability to generate a histogram of functions called. + +;;; User customization variables: +;;; +;;; byte-compile-verbose Whether to report the function currently being +;;; compiled in the minibuffer; +;;; byte-optimize Whether to do optimizations; this may be +;;; t, nil, 'source, or 'byte; +;;; byte-optimize-log Whether to report (in excruciating detail) +;;; exactly which optimizations have been made. +;;; This may be t, nil, 'source, or 'byte; +;;; byte-compile-error-on-warn Whether to stop compilation when a warning is +;;; produced; +;;; byte-compile-delete-errors Whether the optimizer may delete calls or +;;; variable references that are side-effect-free +;;; except that they may return an error. +;;; byte-compile-generate-call-tree Whether to generate a histogram of +;;; function calls. This can be useful for +;;; finding unused functions, as well as simple +;;; performance metering. +;;; byte-compile-warnings List of warnings to issue, or t. May contain +;;; 'free-vars (references to variables not in the +;;; current lexical scope) +;;; 'unused-vars (non-global variables bound but +;;; not referenced) +;;; 'unresolved (calls to unknown functions) +;;; 'callargs (lambda calls with args that don't +;;; match the lambda's definition) +;;; 'redefine (function cell redefined from +;;; a macro to a lambda or vice versa, +;;; or redefined to take other args) +;;; 'obsolete (obsolete variables and functions) +;;; 'pedantic (references to Emacs-compatible +;;; symbols) +;;; byte-compile-emacs19-compatibility Whether the compiler should +;;; generate .elc files which can be loaded into +;;; generic emacs 19. +;;; emacs-lisp-file-regexp Regexp for the extension of source-files; +;;; see also the function byte-compile-dest-file. +;;; byte-compile-overwrite-file If nil, delete old .elc files before saving. +;;; +;;; Most of the above parameters can also be set on a file-by-file basis; see +;;; the documentation of the `byte-compiler-options' macro. + +;;; New Features: +;;; +;;; o The form `defsubst' is just like `defun', except that the function +;;; generated will be open-coded in compiled code which uses it. This +;;; means that no function call will be generated, it will simply be +;;; spliced in. Lisp functions calls are very slow, so this can be a +;;; big win. +;;; +;;; You can generally accomplish the same thing with `defmacro', but in +;;; that case, the defined procedure can't be used as an argument to +;;; mapcar, etc. +;;; +;;; o You can make a given function be inline even if it has already been +;;; defined with `defun' by using the `proclaim-inline' form like so: +;;; (proclaim-inline my-function) +;;; This is, in fact, exactly what `defsubst' does. To make a function no +;;; longer be inline, you must use `proclaim-notinline'. Beware that if +;;; you define a function with `defsubst' and later redefine it with +;;; `defun', it will still be open-coded until you use proclaim-notinline. +;;; +;;; o You can also open-code one particular call to a function without +;;; open-coding all calls. Use the 'inline' form to do this, like so: +;;; +;;; (inline (foo 1 2 3)) ;; `foo' will be open-coded +;;; or... +;;; (inline ;; `foo' and `baz' will be +;;; (foo 1 2 3 (bar 5)) ;; open-coded, but `bar' will not. +;;; (baz 0)) +;;; +;;; o It is possible to open-code a function in the same file it is defined +;;; in without having to load that file before compiling it. the +;;; byte-compiler has been modified to remember function definitions in +;;; the compilation environment in the same way that it remembers macro +;;; definitions. +;;; +;;; o Forms like ((lambda ...) ...) are open-coded. +;;; +;;; o The form `eval-when-compile' is like progn, except that the body +;;; is evaluated at compile-time. When it appears at top-level, this +;;; is analogous to the Common Lisp idiom (eval-when (compile) ...). +;;; When it does not appear at top-level, it is similar to the +;;; Common Lisp #. reader macro (but not in interpreted code). +;;; +;;; o The form `eval-and-compile' is similar to eval-when-compile, but +;;; the whole form is evalled both at compile-time and at run-time. +;;; +;;; o The command M-x byte-compile-and-load-file does what you'd think. +;;; +;;; o The command compile-defun is analogous to eval-defun. +;;; +;;; o If you run byte-compile-file on a filename which is visited in a +;;; buffer, and that buffer is modified, you are asked whether you want +;;; to save the buffer before compiling. +;;; +;;; o You can add this to /etc/magic to make file(1) recognise the files +;;; generated by this compiler: +;;; +;;; 0 string ;ELC GNU Emacs Lisp compiled file, +;;; >4 byte x version %d +;;; +;;; TO DO: +;;; +;;; o Should implement declarations and proclamations, notably special, +;;; unspecial, and ignore. Do this in such a way as to not break cl.el. +;;; o The bound-but-not-used warnings are not issued for variables whose +;;; bindings were established in the arglist, due to the lack of an +;;; ignore declaration. Once ignore exists, this should be turned on. +;;; o Warn about functions and variables defined but not used? +;;; Maybe add some kind of `export' declaration for this? +;;; (With interactive functions being automatically exported?) +;;; o Any reference to a variable, even one which is a no-op, will cause +;;; the warning not to be given. Possibly we could use the for-effect +;;; flag to determine when this reference is useless; possibly more +;;; complex flow analysis would be necessary. +;;; o If the optimizer deletes a variable reference, we might be left with +;;; a bound-but-not-referenced warning. Generally this is ok, but not if +;;; it's a synergistic result of macroexpansion. Need some way to note +;;; that a varref is being optimized away? Of course it would be nice to +;;; optimize away the binding too, someday, but it's unsafe today. +;;; o (See byte-optimize.el for the optimization TODO list.) + +(require 'backquote) + +(or (fboundp 'defsubst) + ;; This really ought to be loaded already! + (load-library "bytecomp-runtime")) + +(eval-when-compile + (defvar byte-compile-single-version nil + "If this is true, the choice of emacs version (v19 or v20) byte-codes will +be hard-coded into bytecomp when it compiles itself. If the compiler itself +is compiled with optimization, this causes a speedup.") + + (cond (byte-compile-single-version + (defmacro byte-compile-single-version () t) + (defmacro byte-compile-version-cond (cond) (list 'quote (eval cond)))) + (t + (defmacro byte-compile-single-version () nil) + (defmacro byte-compile-version-cond (cond) cond))) + ) + +(defvar emacs-lisp-file-regexp (if (eq system-type 'vax-vms) + (purecopy "\\.EL\\(;[0-9]+\\)?$") + (purecopy "\\.el$")) + "*Regexp which matches Emacs Lisp source files. +You may want to redefine `byte-compile-dest-file' if you change this.") + +;; This enables file name handlers such as jka-compr +;; to remove parts of the file name that should not be copied +;; through to the output file name. +(defun byte-compiler-base-file-name (filename) + (let ((handler (find-file-name-handler filename + 'byte-compiler-base-file-name))) + (if handler + (funcall handler 'byte-compiler-base-file-name filename) + filename))) + +(or (fboundp 'byte-compile-dest-file) + ;; The user may want to redefine this along with emacs-lisp-file-regexp, + ;; so only define it if it is undefined. + (defun byte-compile-dest-file (filename) + "Convert an Emacs Lisp source file name to a compiled file name." + (setq filename (byte-compiler-base-file-name filename)) + (setq filename (file-name-sans-versions filename)) + (cond ((eq system-type 'vax-vms) + (concat (substring filename 0 (string-match ";" filename)) "c")) + ((string-match emacs-lisp-file-regexp filename) + (concat (substring filename 0 (match-beginning 0)) ".elc")) + (t (concat filename ".elc"))))) + +;; This can be the 'byte-compile property of any symbol. +(autoload 'byte-compile-inline-expand "byte-optimize") + +;; This is the entrypoint to the lapcode optimizer pass1. +(autoload 'byte-optimize-form "byte-optimize") +;; This is the entrypoint to the lapcode optimizer pass2. +(autoload 'byte-optimize-lapcode "byte-optimize") +(autoload 'byte-compile-unfold-lambda "byte-optimize") + +;; This is the entry point to the decompiler, which is used by the +;; disassembler. The disassembler just requires 'byte-compile, but +;; that doesn't define this function, so this seems to be a reasonable +;; thing to do. +(autoload 'byte-decompile-bytecode "byte-opt") + +(defvar byte-compile-verbose + (and (not noninteractive) (> (device-baud-rate) search-slow-speed)) + "*Non-nil means print messages describing progress of byte-compiler.") + +(defvar byte-compile-emacs19-compatibility + (not (emacs-version>= 20)) + "*Non-nil means generate output that can run in Emacs 19.") + +(defvar byte-optimize t + "*Enables optimization in the byte compiler. +nil means don't do any optimization. +t means do all optimizations. +`source' means do source-level optimizations only. +`byte' means do code-level optimizations only.") + +(defvar byte-compile-delete-errors t + "*If non-nil, the optimizer may delete forms that may signal an error. +This includes variable references and calls to functions such as `car'.") + +;; XEmacs addition +(defvar byte-compile-new-bytecodes nil + "This is completely ignored. It is only around for backwards +compatibility.") + + +;; FSF enables byte-compile-dynamic-docstrings but not byte-compile-dynamic +;; by default. This would be a reasonable conservative approach except +;; for the fact that if you enable either of these, you get incompatible +;; byte code that can't be read by XEmacs 19.13 or before or FSF 19.28 or +;; before. +;; +;; Therefore, neither is enabled for 19.14. Both are enabled for 20.0 +;; because we have no reason to be conservative about changing the +;; way things work. (Ben) + +;; However, I don't think that defaulting byte-compile-dynamic to nil +;; is a compatibility issue - rather it is a performance issue. +;; Therefore I am setting byte-compile-dynamic back to nil. (mrb) + +(defvar byte-compile-dynamic nil + "*If non-nil, compile function bodies so they load lazily. +They are hidden comments in the compiled file, and brought into core when the +function is called. + +To enable this option, make it a file-local variable +in the source file you want it to apply to. +For example, add -*-byte-compile-dynamic: t;-*- on the first line. + +When this option is true, if you load the compiled file and then move it, +the functions you loaded will not be able to run.") + +(defvar byte-compile-dynamic-docstrings (emacs-version>= 20) + "*If non-nil, compile doc strings for lazy access. +We bury the doc strings of functions and variables +inside comments in the file, and bring them into core only when they +are actually needed. + +When this option is true, if you load the compiled file and then move it, +you won't be able to find the documentation of anything in that file. + +To disable this option for a certain file, make it a file-local variable +in the source file. For example, add this to the first line: + -*-byte-compile-dynamic-docstrings:nil;-*- +You can also set the variable globally. + +This option is enabled by default because it reduces Emacs memory usage.") + +(defvar byte-optimize-log nil + "*If true, the byte-compiler will log its optimizations into *Compile-Log*. +If this is 'source, then only source-level optimizations will be logged. +If it is 'byte, then only byte-level optimizations will be logged.") + +(defvar byte-compile-error-on-warn nil + "*If true, the byte-compiler reports warnings with `error'.") + +;; byte-compile-warning-types in FSF. +(defvar byte-compile-default-warnings + '(redefine callargs free-vars unresolved unused-vars obsolete) + "*The warnings used when byte-compile-warnings is t.") + +(defvar byte-compile-warnings t + "*List of warnings that the compiler should issue (t for the default set). +Elements of the list may be: + + free-vars references to variables not in the current lexical scope. + unused-vars references to non-global variables bound but not referenced. + unresolved calls to unknown functions. + callargs lambda calls with args that don't match the definition. + redefine function cell redefined from a macro to a lambda or vice + versa, or redefined to take a different number of arguments. + obsolete use of an obsolete function or variable. + pedantic warn of use of compatible symbols. + +The default set is specified by `byte-compile-default-warnings' and +normally encompasses all possible warnings. + +See also the macro `byte-compiler-options'.") + +(defvar byte-compile-generate-call-tree nil + "*Non-nil means collect call-graph information when compiling. +This records functions were called and from where. +If the value is t, compilation displays the call graph when it finishes. +If the value is neither t nor nil, compilation asks you whether to display +the graph. + +The call tree only lists functions called, not macros used. Those functions +which the byte-code interpreter knows about directly (eq, cons, etc.) are +not reported. + +The call tree also lists those functions which are not known to be called +\(that is, to which no calls have been compiled). Functions which can be +invoked interactively are excluded from this list.") + +(defconst byte-compile-call-tree nil "Alist of functions and their call tree. +Each element looks like + + \(FUNCTION CALLERS CALLS\) + +where CALLERS is a list of functions that call FUNCTION, and CALLS +is a list of functions for which calls were generated while compiling +FUNCTION.") + +(defvar byte-compile-call-tree-sort 'name + "*If non-nil, sort the call tree. +The values `name', `callers', `calls', `calls+callers' +specify different fields to sort on.") + +(defvar byte-compile-overwrite-file t + "If nil, old .elc files are deleted before the new is saved, and .elc +files will have the same modes as the corresponding .el file. Otherwise, +existing .elc files will simply be overwritten, and the existing modes +will not be changed. If this variable is nil, then an .elc file which +is a symbolic link will be turned into a normal file, instead of the file +which the link points to being overwritten.") + +(defvar byte-recompile-directory-ignore-errors-p nil + "If true, then `byte-recompile-directory' will continue compiling even +when an error occurs in a file. This is bound to t by +`batch-byte-recompile-directory'.") + +(defvar byte-recompile-directory-recursively t + "*If true, then `byte-recompile-directory' will recurse on subdirectories.") + +(defvar byte-compile-constants nil + "list of all constants encountered during compilation of this form") +(defvar byte-compile-variables nil + "list of all variables encountered during compilation of this form") +(defvar byte-compile-bound-variables nil + "Alist of variables bound in the context of the current form, +that is, the current lexical environment. This list lives partly +on the specbind stack. The cdr of each cell is an integer bitmask.") + +(defconst byte-compile-referenced-bit 1) +(defconst byte-compile-assigned-bit 2) +(defconst byte-compile-arglist-bit 4) +(defconst byte-compile-global-bit 8) + +(defvar byte-compile-free-references) +(defvar byte-compile-free-assignments) + +(defvar byte-compiler-error-flag) + +(defconst byte-compile-initial-macro-environment + (purecopy + '((byte-compiler-options . (lambda (&rest forms) + (apply 'byte-compiler-options-handler forms))) + (eval-when-compile . (lambda (&rest body) + (list 'quote (eval (byte-compile-top-level + (cons 'progn body)))))) + (eval-and-compile . (lambda (&rest body) + (eval (cons 'progn body)) + (cons 'progn body))))) + "The default macro-environment passed to macroexpand by the compiler. +Placing a macro here will cause a macro to have different semantics when +expanded by the compiler as when expanded by the interpreter.") + +(defvar byte-compile-macro-environment byte-compile-initial-macro-environment + "Alist of macros defined in the file being compiled. +Each element looks like (MACRONAME . DEFINITION). It is +\(MACRONAME . nil) when a macro is redefined as a function.") + +(defvar byte-compile-function-environment nil + "Alist of functions defined in the file being compiled. +This is so we can inline them when necessary. +Each element looks like (FUNCTIONNAME . DEFINITION). It is +\(FUNCTIONNAME . nil) when a function is redefined as a macro.") + +(defvar byte-compile-autoload-environment nil + "Alist of functions and macros defined by autoload in the file being compiled. +This is so we can suppress warnings about calls to these functions, even though +they do not have `real' definitions. +Each element looks like (FUNCTIONNAME . CALL-TO-AUTOLOAD).") + +(defvar byte-compile-unresolved-functions nil + "Alist of undefined functions to which calls have been compiled (used for +warnings when the function is later defined with incorrect args).") + +(defvar byte-compile-file-domain) ; domain of file being compiled + +(defvar byte-compile-tag-number 0) +(defvar byte-compile-output nil + "Alist describing contents to put in byte code string. +Each element is (INDEX . VALUE)") +(defvar byte-compile-depth 0 "Current depth of execution stack.") +(defvar byte-compile-maxdepth 0 "Maximum depth of execution stack.") + + +;;; The byte codes; this information is duplicated in bytecode.c + +(defconst byte-code-vector nil + "An array containing byte-code names indexed by byte-code values.") + +(defconst byte-stack+-info nil + "An array with the stack adjustment for each byte-code.") + +(defmacro byte-defop (opcode stack-adjust opname &optional docstring) + ;; This is a speed-hack for building the byte-code-vector at compile-time. + ;; We fill in the vector at macroexpand-time, and then after the last call + ;; to byte-defop, we write the vector out as a constant instead of writing + ;; out a bunch of calls to aset. + ;; Actually, we don't fill in the vector itself, because that could make + ;; it problematic to compile big changes to this compiler; we store the + ;; values on its plist, and remove them later in -extrude. + (let ((v1 (or (get 'byte-code-vector 'tmp-compile-time-value) + (put 'byte-code-vector 'tmp-compile-time-value + (make-vector 256 nil)))) + (v2 (or (get 'byte-stack+-info 'tmp-compile-time-value) + (put 'byte-stack+-info 'tmp-compile-time-value + (make-vector 256 nil))))) + (aset v1 opcode opname) + (aset v2 opcode stack-adjust)) + (if docstring + (list 'defconst opname opcode (concat "Byte code opcode " docstring ".")) + (list 'defconst opname opcode))) + +(defmacro byte-extrude-byte-code-vectors () + (prog1 (list 'setq 'byte-code-vector + (get 'byte-code-vector 'tmp-compile-time-value) + 'byte-stack+-info + (get 'byte-stack+-info 'tmp-compile-time-value)) + (remprop 'byte-code-vector 'tmp-compile-time-value) + (remprop 'byte-stack+-info 'tmp-compile-time-value))) + + +;; unused: 0-7 + +;; These opcodes are special in that they pack their argument into the +;; opcode word. +;; +(byte-defop 8 1 byte-varref "for variable reference") +(byte-defop 16 -1 byte-varset "for setting a variable") +(byte-defop 24 -1 byte-varbind "for binding a variable") +(byte-defop 32 0 byte-call "for calling a function") +(byte-defop 40 0 byte-unbind "for unbinding special bindings") +;; codes 8-47 are consumed by the preceding opcodes + +;; unused: 48-55 + +(byte-defop 56 -1 byte-nth) +(byte-defop 57 0 byte-symbolp) +(byte-defop 58 0 byte-consp) +(byte-defop 59 0 byte-stringp) +(byte-defop 60 0 byte-listp) +(byte-defop 61 -1 byte-old-eq) +(byte-defop 62 -1 byte-old-memq) +(byte-defop 63 0 byte-not) +(byte-defop 64 0 byte-car) +(byte-defop 65 0 byte-cdr) +(byte-defop 66 -1 byte-cons) +(byte-defop 67 0 byte-list1) +(byte-defop 68 -1 byte-list2) +(byte-defop 69 -2 byte-list3) +(byte-defop 70 -3 byte-list4) +(byte-defop 71 0 byte-length) +(byte-defop 72 -1 byte-aref) +(byte-defop 73 -2 byte-aset) +(byte-defop 74 0 byte-symbol-value) +(byte-defop 75 0 byte-symbol-function) ; this was commented out +(byte-defop 76 -1 byte-set) +(byte-defop 77 -1 byte-fset) ; this was commented out +(byte-defop 78 -1 byte-get) +(byte-defop 79 -2 byte-substring) +(byte-defop 80 -1 byte-concat2) +(byte-defop 81 -2 byte-concat3) +(byte-defop 82 -3 byte-concat4) +(byte-defop 83 0 byte-sub1) +(byte-defop 84 0 byte-add1) +(byte-defop 85 -1 byte-eqlsign) +(byte-defop 86 -1 byte-gtr) +(byte-defop 87 -1 byte-lss) +(byte-defop 88 -1 byte-leq) +(byte-defop 89 -1 byte-geq) +(byte-defop 90 -1 byte-diff) +(byte-defop 91 0 byte-negate) +(byte-defop 92 -1 byte-plus) +(byte-defop 93 -1 byte-max) +(byte-defop 94 -1 byte-min) +(byte-defop 95 -1 byte-mult) +(byte-defop 96 1 byte-point) +(byte-defop 97 -1 byte-eq) ; new as of v20 +(byte-defop 98 0 byte-goto-char) +(byte-defop 99 0 byte-insert) +(byte-defop 100 1 byte-point-max) +(byte-defop 101 1 byte-point-min) +(byte-defop 102 0 byte-char-after) +(byte-defop 103 1 byte-following-char) +(byte-defop 104 1 byte-preceding-char) +(byte-defop 105 1 byte-current-column) +(byte-defop 106 0 byte-indent-to) +(byte-defop 107 -1 byte-equal) ; new as of v20 +(byte-defop 108 1 byte-eolp) +(byte-defop 109 1 byte-eobp) +(byte-defop 110 1 byte-bolp) +(byte-defop 111 1 byte-bobp) +(byte-defop 112 1 byte-current-buffer) +(byte-defop 113 0 byte-set-buffer) +(byte-defop 114 0 byte-save-current-buffer + "To make a binding to record the current buffer.") +;;(byte-defop 114 1 byte-read-char-OBSOLETE) ;obsolete as of v19 +(byte-defop 115 -1 byte-memq) ; new as of v20 +(byte-defop 116 1 byte-interactive-p) + +(byte-defop 117 0 byte-forward-char) +(byte-defop 118 0 byte-forward-word) +(byte-defop 119 -1 byte-skip-chars-forward) +(byte-defop 120 -1 byte-skip-chars-backward) +(byte-defop 121 0 byte-forward-line) +(byte-defop 122 0 byte-char-syntax) +(byte-defop 123 -1 byte-buffer-substring) +(byte-defop 124 -1 byte-delete-region) +(byte-defop 125 -1 byte-narrow-to-region) +(byte-defop 126 1 byte-widen) +(byte-defop 127 0 byte-end-of-line) + +;; unused: 128 + +;; These store their argument in the next two bytes +(byte-defop 129 1 byte-constant2 + "for reference to a constant with vector index >= byte-constant-limit") +(byte-defop 130 0 byte-goto "for unconditional jump") +(byte-defop 131 -1 byte-goto-if-nil "to pop value and jump if it's nil") +(byte-defop 132 -1 byte-goto-if-not-nil + "to pop value and jump if it's not nil") +(byte-defop 133 -1 byte-goto-if-nil-else-pop + "to examine top-of-stack, jump and don't pop it if it's nil, +otherwise pop it") +(byte-defop 134 -1 byte-goto-if-not-nil-else-pop + "to examine top-of-stack, jump and don't pop it if it's non nil, +otherwise pop it") + +(byte-defop 135 -1 byte-return "to pop a value and return it from `byte-code'") +(byte-defop 136 -1 byte-discard "to discard one value from stack") +(byte-defop 137 1 byte-dup "to duplicate the top of the stack") + +(byte-defop 138 0 byte-save-excursion + "to make a binding to record the buffer, point and mark") +(byte-defop 139 0 byte-save-window-excursion + "to make a binding to record entire window configuration") +(byte-defop 140 0 byte-save-restriction + "to make a binding to record the current buffer clipping restrictions") +(byte-defop 141 -1 byte-catch + "for catch. Takes, on stack, the tag and an expression for the body") +(byte-defop 142 -1 byte-unwind-protect + "for unwind-protect. Takes, on stack, an expression for the unwind-action") + +;; For condition-case. Takes, on stack, the variable to bind, +;; an expression for the body, and a list of clauses. +(byte-defop 143 -2 byte-condition-case) + +;; For entry to with-output-to-temp-buffer. +;; Takes, on stack, the buffer name. +;; Binds standard-output and does some other things. +;; Returns with temp buffer on the stack in place of buffer name. +(byte-defop 144 0 byte-temp-output-buffer-setup) + +;; For exit from with-output-to-temp-buffer. +;; Expects the temp buffer on the stack underneath value to return. +;; Pops them both, then pushes the value back on. +;; Unbinds standard-output and makes the temp buffer visible. +(byte-defop 145 -1 byte-temp-output-buffer-show) + +;; To unbind back to the beginning of this frame. +;; Not used yet, but will be needed for tail-recursion elimination. +(byte-defop 146 0 byte-unbind-all) + +(byte-defop 147 -2 byte-set-marker) +(byte-defop 148 0 byte-match-beginning) +(byte-defop 149 0 byte-match-end) +(byte-defop 150 0 byte-upcase) +(byte-defop 151 0 byte-downcase) +(byte-defop 152 -1 byte-string=) +(byte-defop 153 -1 byte-string<) +(byte-defop 154 -1 byte-old-equal) +(byte-defop 155 -1 byte-nthcdr) +(byte-defop 156 -1 byte-elt) +(byte-defop 157 -1 byte-old-member) +(byte-defop 158 -1 byte-old-assq) +(byte-defop 159 0 byte-nreverse) +(byte-defop 160 -1 byte-setcar) +(byte-defop 161 -1 byte-setcdr) +(byte-defop 162 0 byte-car-safe) +(byte-defop 163 0 byte-cdr-safe) +(byte-defop 164 -1 byte-nconc) +(byte-defop 165 -1 byte-quo) +(byte-defop 166 -1 byte-rem) +(byte-defop 167 0 byte-numberp) +(byte-defop 168 0 byte-integerp) + +;; unused: 169 + +;; These are not present in FSF. +;; +(byte-defop 170 0 byte-rel-goto) +(byte-defop 171 -1 byte-rel-goto-if-nil) +(byte-defop 172 -1 byte-rel-goto-if-not-nil) +(byte-defop 173 -1 byte-rel-goto-if-nil-else-pop) +(byte-defop 174 -1 byte-rel-goto-if-not-nil-else-pop) + +(byte-defop 175 nil byte-listN) +(byte-defop 176 nil byte-concatN) +(byte-defop 177 nil byte-insertN) + +;; unused: 178-181 + +;; these ops are new to v20 +(byte-defop 182 -1 byte-member) +(byte-defop 183 -1 byte-assq) + +;; unused: 184-191 + +(byte-defop 192 1 byte-constant "for reference to a constant") +;; codes 193-255 are consumed by byte-constant. +(defconst byte-constant-limit 64 + "Exclusive maximum index usable in the `byte-constant' opcode.") + +(defconst byte-goto-ops (purecopy + '(byte-goto byte-goto-if-nil byte-goto-if-not-nil + byte-goto-if-nil-else-pop + byte-goto-if-not-nil-else-pop)) + "List of byte-codes whose offset is a pc.") + +(defconst byte-goto-always-pop-ops + (purecopy '(byte-goto-if-nil byte-goto-if-not-nil))) + +(defconst byte-rel-goto-ops + (purecopy '(byte-rel-goto byte-rel-goto-if-nil byte-rel-goto-if-not-nil + byte-rel-goto-if-nil-else-pop byte-rel-goto-if-not-nil-else-pop)) + "byte-codes for relative jumps.") + +(byte-extrude-byte-code-vectors) + +;;; lapcode generator +;;; +;;; the byte-compiler now does source -> lapcode -> bytecode instead of +;;; source -> bytecode, because it's a lot easier to make optimizations +;;; on lapcode than on bytecode. +;;; +;;; Elements of the lapcode list are of the form ( . ) +;;; where instruction is a symbol naming a byte-code instruction, +;;; and parameter is an argument to that instruction, if any. +;;; +;;; The instruction can be the pseudo-op TAG, which means that this position +;;; in the instruction stream is a target of a goto. (car PARAMETER) will be +;;; the PC for this location, and the whole instruction "(TAG pc)" will be the +;;; parameter for some goto op. +;;; +;;; If the operation is varbind, varref, varset or push-constant, then the +;;; parameter is (variable/constant . index_in_constant_vector). +;;; +;;; First, the source code is macroexpanded and optimized in various ways. +;;; Then the resultant code is compiled into lapcode. Another set of +;;; optimizations are then run over the lapcode. Then the variables and +;;; constants referenced by the lapcode are collected and placed in the +;;; constants-vector. (This happens now so that variables referenced by dead +;;; code don't consume space.) And finally, the lapcode is transformed into +;;; compacted byte-code. +;;; +;;; A distinction is made between variables and constants because the variable- +;;; referencing instructions are more sensitive to the variables being near the +;;; front of the constants-vector than the constant-referencing instructions. +;;; Also, this lets us notice references to free variables. + +(defun byte-compile-lapcode (lap) + "Turns lapcode into bytecode. The lapcode is destroyed." + ;; Lapcode modifications: changes the ID of a tag to be the tag's PC. + (let ((pc 0) ; Program counter + op off ; Operation & offset + (bytes '()) ; Put the output bytes here + (patchlist nil) ; List of tags and goto's to patch + rest rel tmp) + (while lap + (setq op (car (car lap)) + off (cdr (car lap))) + (cond ((not (symbolp op)) + (error "Non-symbolic opcode `%s'" op)) + ((eq op 'TAG) + (setcar off pc) + (setq patchlist (cons off patchlist))) + ((memq op byte-goto-ops) + (setq pc (+ pc 3)) + (setq bytes (cons (cons pc (cdr off)) + (cons nil + (cons (symbol-value op) bytes)))) + (setq patchlist (cons bytes patchlist))) + (t + (setq bytes + (cond ((cond ((consp off) + ;; Variable or constant reference + (setq off (cdr off)) + (eq op 'byte-constant))) + (cond ((< off byte-constant-limit) + (setq pc (1+ pc)) + (cons (+ byte-constant off) bytes)) + (t + (setq pc (+ 3 pc)) + (cons (lsh off -8) + (cons (logand off 255) + (cons byte-constant2 bytes)))))) + ((and (<= byte-listN (symbol-value op)) + (<= (symbol-value op) byte-insertN)) + (setq pc (+ 2 pc)) + (cons off (cons (symbol-value op) bytes))) + ((< off 6) + (setq pc (1+ pc)) + (cons (+ (symbol-value op) off) bytes)) + ((< off 256) + (setq pc (+ 2 pc)) + (cons off (cons (+ (symbol-value op) 6) bytes))) + (t + (setq pc (+ 3 pc)) + (cons (lsh off -8) + (cons (logand off 255) + (cons (+ (symbol-value op) 7) + bytes)))))))) + (setq lap (cdr lap))) + ;;(if (not (= pc (length bytes))) + ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes))) + (cond (t ;; starting with Emacs 19. + ;; Make relative jumps + (setq patchlist (nreverse patchlist)) + (while (progn + (setq off 0) ; PC change because of deleted bytes + (setq rest patchlist) + (while rest + (setq tmp (car rest)) + (and (consp (car tmp)) ; Jump + (prog1 (null (nth 1 tmp)) ; Absolute jump + (setq tmp (car tmp))) + (progn + (setq rel (- (car (cdr tmp)) (car tmp))) + (and (<= -129 rel) (< rel 128))) + (progn + ;; Convert to relative jump. + (setcdr (car rest) (cdr (cdr (car rest)))) + (setcar (cdr (car rest)) + (+ (car (cdr (car rest))) + (- byte-rel-goto byte-goto))) + (setq off (1- off)))) + (setcar tmp (+ (car tmp) off)) ; Adjust PC + (setq rest (cdr rest))) + ;; If optimizing, repeat until no change. + (and byte-optimize + (not (zerop off))))))) + ;; Patch PC into jumps + (let (bytes) + (while patchlist + (setq bytes (car patchlist)) + (cond ((atom (car bytes))) ; Tag + ((nth 1 bytes) ; Relative jump + (setcar bytes (+ (- (car (cdr (car bytes))) (car (car bytes))) + 128))) + (t ; Absolute jump + (setq pc (car (cdr (car bytes)))) ; Pick PC from tag + (setcar (cdr bytes) (logand pc 255)) + (setcar bytes (lsh pc -8)))) + (setq patchlist (cdr patchlist)))) + (concat (nreverse bytes)))) + + +;;; byte compiler messages + +(defvar byte-compile-current-form nil) +(defvar byte-compile-current-file nil) +(defvar byte-compile-dest-file nil) + +(defmacro byte-compile-log (format-string &rest args) + (list 'and + 'byte-optimize + '(memq byte-optimize-log '(t source)) + (list 'let '((print-escape-newlines t) + (print-level 4) + (print-length 4)) + (list 'byte-compile-log-1 + (cons 'format + (cons format-string + (mapcar + '(lambda (x) + (if (symbolp x) (list 'prin1-to-string x) x)) + args))))))) + +(defconst byte-compile-last-warned-form nil) + +;; Log a message STRING in *Compile-Log*. +;; Also log the current function and file if not already done. +(defun byte-compile-log-1 (string &optional fill) + (let ((this-form (or byte-compile-current-form "toplevel forms"))) + (cond + (noninteractive + (if (or byte-compile-current-file + (and byte-compile-last-warned-form + (not (eq this-form byte-compile-last-warned-form)))) + (message + (format "While compiling %s%s:" + this-form + (if byte-compile-current-file + (if (stringp byte-compile-current-file) + (concat " in file " byte-compile-current-file) + (concat " in buffer " + (buffer-name byte-compile-current-file))) + "")))) + (message " %s" string)) + (t + (save-excursion + (set-buffer (get-buffer-create "*Compile-Log*")) + (goto-char (point-max)) + (cond ((or byte-compile-current-file + (and byte-compile-last-warned-form + (not (eq this-form byte-compile-last-warned-form)))) + (if byte-compile-current-file + (insert "\n\^L\n" (current-time-string) "\n")) + (insert "While compiling " + (if (stringp this-form) this-form + (format "%s" this-form))) + (if byte-compile-current-file + (if (stringp byte-compile-current-file) + (insert " in file " byte-compile-current-file) + (insert " in buffer " + (buffer-name byte-compile-current-file)))) + (insert ":\n"))) + (insert " " string "\n") + (if (and fill (not (string-match "\n" string))) + (let ((fill-prefix " ") + (fill-column 78)) + (fill-paragraph nil))) + ))) + (setq byte-compile-current-file nil + byte-compile-last-warned-form this-form))) + +;; Log the start of a file in *Compile-Log*, and mark it as done. +;; But do nothing in batch mode. +(defun byte-compile-log-file () + (and byte-compile-current-file (not noninteractive) + (save-excursion + (set-buffer (get-buffer-create "*Compile-Log*")) + (goto-char (point-max)) + (insert "\n\^L\nCompiling " + (if (stringp byte-compile-current-file) + (concat "file " byte-compile-current-file) + (concat "buffer " (buffer-name byte-compile-current-file))) + " at " (current-time-string) "\n") + (setq byte-compile-current-file nil)))) + +(defun byte-compile-warn (format &rest args) + (setq format (apply 'format format args)) + (if byte-compile-error-on-warn + (error "%s" format) ; byte-compile-file catches and logs it + (byte-compile-log-1 (concat "** " format) t) +;;; RMS says: +;;; It is useless to flash warnings too fast to be read. +;;; Besides, they will all be shown at the end. +;;; and comments out the next two lines. + (or noninteractive ; already written on stdout. + (message "Warning: %s" format)))) + +;;; This function should be used to report errors that have halted +;;; compilation of the current file. +(defun byte-compile-report-error (error-info) + (setq byte-compiler-error-flag t) + (byte-compile-log-1 + (concat "!! " + (format (if (cdr error-info) "%s (%s)" "%s") + (get (car error-info) 'error-message) + (prin1-to-string (cdr error-info)))))) + +;;; Used by make-obsolete. +(defun byte-compile-obsolete (form) + (let ((new (get (car form) 'byte-obsolete-info))) + (if (memq 'obsolete byte-compile-warnings) + (byte-compile-warn "%s is an obsolete function; %s" (car form) + (if (stringp (car new)) + (car new) + (format "use %s instead." (car new))))) + (funcall (or (cdr new) 'byte-compile-normal-call) form))) + +;;; Used by make-obsolete. +(defun byte-compile-compatible (form) + (let ((new (get (car form) 'byte-compatible-info))) + (if (memq 'pedantic byte-compile-warnings) + (byte-compile-warn "%s is provided for compatibility; %s" (car form) + (if (stringp (car new)) + (car new) + (format "use %s instead." (car new))))) + (funcall (or (cdr new) 'byte-compile-normal-call) form))) + +;; Compiler options + +(defconst byte-compiler-legal-options + '((optimize byte-optimize (t nil source byte) val) + (file-format byte-compile-emacs19-compatibility (emacs19 emacs20) + (eq val 'emacs19)) + (delete-errors byte-compile-delete-errors (t nil) val) + (verbose byte-compile-verbose (t nil) val) + (new-bytecodes byte-compile-new-bytecodes (t nil) val) + (warnings byte-compile-warnings + ((callargs redefine free-vars unused-vars unresolved)) + val))) + +;; XEmacs addition +(defconst byte-compiler-obsolete-options + '((new-bytecodes t))) + +;; Inhibit v19/v20 selectors if the version is hardcoded. +;; #### This should print a warning if the user tries to change something +;; than can't be changed because the running compiler doesn't support it. +(cond + ((byte-compile-single-version) + (setcar (cdr (cdr (assq 'file-format byte-compiler-legal-options))) + (if (byte-compile-version-cond byte-compile-emacs19-compatibility) + '(emacs19) '(emacs20))))) + +;; now we can copy it. +(setq byte-compiler-legal-options (purecopy byte-compiler-legal-options)) + +(defun byte-compiler-options-handler (&rest args) + (let (key val desc choices) + (while args + (if (or (atom (car args)) (nthcdr 2 (car args)) (null (cdr (car args)))) + (error "malformed byte-compiler-option %s" (car args))) + (setq key (car (car args)) + val (car (cdr (car args))) + desc (assq key byte-compiler-legal-options)) + (or desc + (error "unknown byte-compiler option %s" key)) + (if (assq key byte-compiler-obsolete-options) + (byte-compile-warn "%s is an obsolete byte-compiler option." key)) + (setq choices (nth 2 desc)) + (if (consp (car choices)) + (let* (this + (handler 'cons) + (var (nth 1 desc)) + (ret (and (memq (car val) '(+ -)) + (copy-sequence (if (eq t (symbol-value var)) + (car choices) + (symbol-value var)))))) + (setq choices (car choices)) + (while val + (setq this (car val)) + (cond ((memq this choices) + (setq ret (funcall handler this ret))) + ((eq this '+) (setq handler 'cons)) + ((eq this '-) (setq handler 'delq)) + ((error "%s only accepts %s." key choices))) + (setq val (cdr val))) + (set (nth 1 desc) ret)) + (or (memq val choices) + (error "%s must be one of %s." key choices)) + (set (nth 1 desc) (eval (nth 3 desc)))) + (setq args (cdr args))) + nil)) + +;;; sanity-checking arglists + +(defun byte-compile-fdefinition (name macro-p) + (let* ((list (if (memq macro-p '(nil subr)) + byte-compile-function-environment + byte-compile-macro-environment)) + (env (cdr (assq name list)))) + (or env + (let ((fn name)) + (while (and (symbolp fn) + (fboundp fn) + (or (symbolp (symbol-function fn)) + (consp (symbol-function fn)) + (and (not macro-p) + (compiled-function-p (symbol-function fn))) + (and (eq macro-p 'subr) (subrp fn)))) + (setq fn (symbol-function fn))) + (if (or (and (not macro-p) (compiled-function-p fn)) + (and (eq macro-p 'subr) (subrp fn))) + fn + (and (consp fn) + (not (eq macro-p 'subr)) + (if (eq 'macro (car fn)) + (cdr fn) + (if macro-p + nil + (if (eq 'autoload (car fn)) + nil + fn))))))))) + +(defun byte-compile-arglist-signature (arglist) + (let ((args 0) + opts + restp) + (while arglist + (cond ((eq (car arglist) '&optional) + (or opts (setq opts 0))) + ((eq (car arglist) '&rest) + (if (cdr arglist) + (setq restp t + arglist nil))) + (t + (if opts + (setq opts (1+ opts)) + (setq args (1+ args))))) + (setq arglist (cdr arglist))) + (cons args (if restp nil (if opts (+ args opts) args))))) + + +(defun byte-compile-arglist-signatures-congruent-p (old new) + (not (or + (> (car new) (car old)) ; requires more args now + (and (null (cdr old)) ; tooks rest-args, doesn't any more + (cdr new)) + (and (cdr new) (cdr old) ; can't take as many args now + (< (cdr new) (cdr old))) + ))) + +(defun byte-compile-arglist-signature-string (signature) + (cond ((null (cdr signature)) + (format "%d+" (car signature))) + ((= (car signature) (cdr signature)) + (format "%d" (car signature))) + (t (format "%d-%d" (car signature) (cdr signature))))) + + +;; Warn if the form is calling a function with the wrong number of arguments. +(defun byte-compile-callargs-warn (form) + (let* ((def (or (byte-compile-fdefinition (car form) nil) + (byte-compile-fdefinition (car form) t))) + (sig (and def (byte-compile-arglist-signature + (if (eq 'lambda (car-safe def)) + (nth 1 def) + (if (compiled-function-p def) + (compiled-function-arglist def) + '(&rest def)))))) + (ncall (length (cdr form)))) + (if (and (null def) + (fboundp 'subr-min-args) + (setq def (byte-compile-fdefinition (car form) 'subr))) + (setq sig (cons (subr-min-args def) (subr-max-args def)))) + (if sig + (if (or (< ncall (car sig)) + (and (cdr sig) (> ncall (cdr sig)))) + (byte-compile-warn + "%s called with %d argument%s, but %s %s" + (car form) ncall + (if (= 1 ncall) "" "s") + (if (< ncall (car sig)) + "requires" + "accepts only") + (byte-compile-arglist-signature-string sig))) + (or (fboundp (car form)) ; might be a subr or autoload. + ;; ## this doesn't work with recursion. + (eq (car form) byte-compile-current-form) + ;; It's a currently-undefined function. + ;; Remember number of args in call. + (let ((cons (assq (car form) byte-compile-unresolved-functions)) + (n (length (cdr form)))) + (if cons + (or (memq n (cdr cons)) + (setcdr cons (cons n (cdr cons)))) + (setq byte-compile-unresolved-functions + (cons (list (car form) n) + byte-compile-unresolved-functions)))))))) + +;; Warn if the function or macro is being redefined with a different +;; number of arguments. +(defun byte-compile-arglist-warn (form macrop) + (let ((old (byte-compile-fdefinition (nth 1 form) macrop))) + (if old + (let ((sig1 (byte-compile-arglist-signature + (if (eq 'lambda (car-safe old)) + (nth 1 old) + (if (compiled-function-p old) + (compiled-function-arglist old) + '(&rest def))))) + (sig2 (byte-compile-arglist-signature (nth 2 form)))) + (or (byte-compile-arglist-signatures-congruent-p sig1 sig2) + (byte-compile-warn "%s %s used to take %s %s, now takes %s" + (if (eq (car form) 'defun) "function" "macro") + (nth 1 form) + (byte-compile-arglist-signature-string sig1) + (if (equal sig1 '(1 . 1)) "argument" "arguments") + (byte-compile-arglist-signature-string sig2)))) + ;; This is the first definition. See if previous calls are compatible. + (let ((calls (assq (nth 1 form) byte-compile-unresolved-functions)) + nums sig min max) + (if calls + (progn + (setq sig (byte-compile-arglist-signature (nth 2 form)) + nums (sort (copy-sequence (cdr calls)) (function <)) + min (car nums) + max (car (nreverse nums))) + (if (or (< min (car sig)) + (and (cdr sig) (> max (cdr sig)))) + (byte-compile-warn + "%s being defined to take %s%s, but was previously called with %s" + (nth 1 form) + (byte-compile-arglist-signature-string sig) + (if (equal sig '(1 . 1)) " arg" " args") + (byte-compile-arglist-signature-string (cons min max)))) + + (setq byte-compile-unresolved-functions + (delq calls byte-compile-unresolved-functions))))) + ))) + +;; If we have compiled any calls to functions which are not known to be +;; defined, issue a warning enumerating them. +;; `unresolved' in the list `byte-compile-warnings' disables this. +(defun byte-compile-warn-about-unresolved-functions (&optional msg) + (if (memq 'unresolved byte-compile-warnings) + (let ((byte-compile-current-form (or msg "the end of the data"))) + ;; First delete the autoloads from the list. + (if byte-compile-autoload-environment + (let ((rest byte-compile-unresolved-functions)) + (while rest + (if (assq (car (car rest)) byte-compile-autoload-environment) + (setq byte-compile-unresolved-functions + (delq (car rest) byte-compile-unresolved-functions))) + (setq rest (cdr rest))))) + ;; Now warn. + (if (cdr byte-compile-unresolved-functions) + (let* ((str "The following functions are not known to be defined: ") + (L (+ (length str) 5)) + (rest (reverse byte-compile-unresolved-functions)) + s) + (while rest + (setq s (symbol-name (car (car rest))) + L (+ L (length s) 2) + rest (cdr rest)) + (if (<= L (1- fill-column)) + (setq str (concat str " " s (and rest ","))) + (setq str (concat str "\n " s (and rest ",")) + L (+ (length s) 4)))) + (byte-compile-warn "%s" str)) + (if byte-compile-unresolved-functions + (byte-compile-warn "the function %s is not known to be defined." + (car (car byte-compile-unresolved-functions))))))) + nil) + +(defun byte-compile-defvar-p (var) + ;; Whether the byte compiler thinks that nonexical references to this + ;; variable are ok. + (or (globally-boundp var) + (let ((rest byte-compile-bound-variables)) + (while (and rest var) + (if (and (eq var (car-safe (car rest))) + (not (= 0 (logand (cdr (car rest)) + byte-compile-global-bit)))) + (setq var nil)) + (setq rest (cdr rest))) + ;; if var is nil at this point, it's a defvar in this file. + (not var)))) + + +;;; If we have compiled bindings of variables which have no referents, warn. +(defun byte-compile-warn-about-unused-variables () + (let ((rest byte-compile-bound-variables) + (unreferenced '()) + cell) + (while (and rest + ;; only warn about variables whose lifetime is now ending, + ;; that is, variables from the lexical scope that is now + ;; terminating. (Think nested lets.) + (not (eq (car rest) 'new-scope))) + (setq cell (car rest)) + (if (and (= 0 (logand byte-compile-referenced-bit (cdr cell))) + ;; Don't warn about declared-but-unused arguments, + ;; for two reasons: first, the arglist structure + ;; might be imposed by external forces, and we don't + ;; have (declare (ignore x)) yet; and second, inline + ;; expansion produces forms like + ;; ((lambda (arg) (byte-code "..." [arg])) x) + ;; which we can't (ok, well, don't) recognise as + ;; containing a reference to arg, so every inline + ;; expansion would generate a warning. (If we had + ;; `ignore' then inline expansion could emit an + ;; ignore declaration.) + (= 0 (logand byte-compile-arglist-bit (cdr cell))) + ;; Don't warn about defvars because this is a + ;; legitimate special binding. + (not (byte-compile-defvar-p (car cell)))) + (setq unreferenced (cons (car cell) unreferenced))) + (setq rest (cdr rest))) + (setq unreferenced (nreverse unreferenced)) + (while unreferenced + (byte-compile-warn + (format "variable %s bound but not referenced" (car unreferenced))) + (setq unreferenced (cdr unreferenced))))) + + +(defmacro byte-compile-constp (form) + ;; Returns non-nil if FORM is a constant. + (` (cond ((consp (, form)) (eq (car (, form)) 'quote)) + ((not (symbolp (, form)))) + ((keywordp (, form))) + ((memq (, form) '(nil t)))))) + +(defmacro byte-compile-close-variables (&rest body) + (cons 'let + (cons '(;; + ;; Close over these variables to encapsulate the + ;; compilation state + ;; + (byte-compile-macro-environment + ;; Copy it because the compiler may patch into the + ;; macroenvironment. + (copy-alist byte-compile-initial-macro-environment)) + (byte-compile-function-environment nil) + (byte-compile-autoload-environment nil) + (byte-compile-unresolved-functions nil) + (byte-compile-bound-variables nil) + (byte-compile-free-references nil) + (byte-compile-free-assignments nil) + ;; + ;; Close over these variables so that `byte-compiler-options' + ;; can change them on a per-file basis. + ;; + (byte-compile-verbose byte-compile-verbose) + (byte-optimize byte-optimize) + (byte-compile-emacs19-compatibility + byte-compile-emacs19-compatibility) + (byte-compile-dynamic byte-compile-dynamic) + (byte-compile-dynamic-docstrings + byte-compile-dynamic-docstrings) + (byte-compile-warnings (if (eq byte-compile-warnings t) + byte-compile-default-warnings + byte-compile-warnings)) + (byte-compile-file-domain nil) + ) + (list + (list 'prog1 (cons 'progn body) + '(if (memq 'unused-vars byte-compile-warnings) + ;; done compiling in this scope, warn now. + (byte-compile-warn-about-unused-variables))))))) + + +(defvar byte-compile-warnings-point-max nil) +(defmacro displaying-byte-compile-warnings (&rest body) + (list 'let + '((byte-compile-warnings-point-max byte-compile-warnings-point-max)) + ;; Log the file name. + '(byte-compile-log-file) + ;; Record how much is logged now. + ;; We will display the log buffer if anything more is logged + ;; before the end of BODY. + '(or byte-compile-warnings-point-max + (save-excursion + (set-buffer (get-buffer-create "*Compile-Log*")) + (setq byte-compile-warnings-point-max (point-max)))) + (list 'unwind-protect + (list 'condition-case 'error-info + (cons 'progn body) + '(error + (byte-compile-report-error error-info))) + '(save-excursion + ;; If there were compilation warnings, display them. + (set-buffer "*Compile-Log*") + (if (= byte-compile-warnings-point-max (point-max)) + nil + (select-window + (prog1 (selected-window) + (select-window (display-buffer (current-buffer))) + (goto-char byte-compile-warnings-point-max) + (recenter 1)))))))) + + +;;;###autoload +(defun byte-force-recompile (directory) + "Recompile every `.el' file in DIRECTORY that already has a `.elc' file. +Files in subdirectories of DIRECTORY are processed also." + (interactive "DByte force recompile (directory): ") + (byte-recompile-directory directory nil t)) + +;;;###autoload +(defun byte-recompile-directory (directory &optional arg norecursion force) + "Recompile every `.el' file in DIRECTORY that needs recompilation. +This is if a `.elc' file exists but is older than the `.el' file. +Files in subdirectories of DIRECTORY are processed also unless argument +NORECURSION is non-nil. + +If the `.elc' file does not exist, normally the `.el' file is *not* compiled. +But a prefix argument (optional second arg) means ask user, +for each such `.el' file, whether to compile it. Prefix argument 0 means +don't ask and compile the file anyway. + +A nonzero prefix argument also means ask about each subdirectory. + +If the fourth argument FORCE is non-nil, +recompile every `.el' file that already has a `.elc' file." + (interactive "DByte recompile directory: \nP") + (if arg + (setq arg (prefix-numeric-value arg))) + (if noninteractive + nil + (save-some-buffers) + (redraw-modeline)) + (let ((directories (list (expand-file-name directory))) + (file-count 0) + (dir-count 0) + last-dir) + (displaying-byte-compile-warnings + (while directories + (setq directory (file-name-as-directory (car directories))) + (or noninteractive (message "Checking %s..." directory)) + (let ((files (directory-files directory)) + source dest) + (while files + (setq source (expand-file-name (car files) directory)) + (if (and (not (member (car files) '("." ".." "RCS" "CVS" "SCCS"))) + ;; Stay away from directory back-links, etc: + (not (file-symlink-p source)) + (file-directory-p source) + byte-recompile-directory-recursively) + ;; This file is a subdirectory. Handle them differently. + (if (or (null arg) + (eq arg 0) + (y-or-n-p (concat "Check " source "? "))) + (setq directories + (nconc directories (list source)))) + ;; It is an ordinary file. Decide whether to compile it. + (if (and (string-match emacs-lisp-file-regexp source) + (not (auto-save-file-name-p source)) + (setq dest (byte-compile-dest-file source)) + (if (file-exists-p dest) + ;; File was already compiled. + (or force (file-newer-than-file-p source dest)) + ;; No compiled file exists yet. + (and arg + (or (eq 0 arg) + (y-or-n-p (concat "Compile " source "? ")))))) + (progn ;(if (and noninteractive (not byte-compile-verbose)) + ; (message "Compiling %s..." source)) + ; we do this in byte-compile-file. + (if byte-recompile-directory-ignore-errors-p + (batch-byte-compile-1 source) + (byte-compile-file source)) + (or noninteractive + (message "Checking %s..." directory)) + (setq file-count (1+ file-count)) + (if (not (eq last-dir directory)) + (setq last-dir directory + dir-count (1+ dir-count))) + ))) + (setq files (cdr files)))) + (setq directories (cdr directories)))) + (message "Done (Total of %d file%s compiled%s)" + file-count (if (= file-count 1) "" "s") + (if (> dir-count 1) (format " in %d directories" dir-count) "")))) + +;;;###autoload +(defun byte-recompile-file (filename &optional force) + "Recompile a file of Lisp code named FILENAME if it needs recompilation. +This is if the `.elc' file exists but is older than the `.el' file. + +If the `.elc' file does not exist, normally the `.el' file is *not* +compiled. But a prefix argument (optional second arg) means ask user +whether to compile it. Prefix argument 0 don't ask and recompile anyway." + (interactive "fByte recompile file: \nP") + (let ((dest)) + (if (and (string-match emacs-lisp-file-regexp filename) + (not (auto-save-file-name-p filename)) + (setq dest (byte-compile-dest-file filename)) + (if (file-exists-p dest) + (file-newer-than-file-p filename dest) + (and force + (or (eq 0 force) + (y-or-n-p (concat "Compile " filename "? ")))))) + (byte-compile-file filename)))) + +(defvar kanji-flag nil) + +;;;###autoload +(defun byte-compile-file (filename &optional load) + "Compile a file of Lisp code named FILENAME into a file of byte code. +The output file's name is made by appending `c' to the end of FILENAME. +With prefix arg (noninteractively: 2nd arg), load the file after compiling." +;; (interactive "fByte compile file: \nP") + (interactive + (let ((file buffer-file-name) + (file-name nil) + (file-dir nil)) + (and file + (eq (cdr (assq 'major-mode (buffer-local-variables))) + 'emacs-lisp-mode) + (setq file-name (file-name-nondirectory file) + file-dir (file-name-directory file))) + (list (read-file-name (if current-prefix-arg + "Byte compile and load file: " + "Byte compile file: ") + file-dir nil nil file-name) + current-prefix-arg))) + ;; Expand now so we get the current buffer's defaults + (setq filename (expand-file-name filename)) + + ;; If we're compiling a file that's in a buffer and is modified, offer + ;; to save it first. + (or noninteractive + (let ((b (get-file-buffer (expand-file-name filename)))) + (if (and b (buffer-modified-p b) + (y-or-n-p (format "save buffer %s first? " (buffer-name b)))) + (save-excursion (set-buffer b) (save-buffer))))) + + (if (or noninteractive byte-compile-verbose) ; XEmacs change + (message "Compiling %s..." filename)) + (let (;;(byte-compile-current-file (file-name-nondirectory filename)) + (byte-compile-current-file filename) + (debug-issue-ebola-notices 0) ; Hack -slb + target-file input-buffer output-buffer + byte-compile-dest-file) + (setq target-file (byte-compile-dest-file filename)) + (setq byte-compile-dest-file target-file) + (save-excursion + (setq input-buffer (get-buffer-create " *Compiler Input*")) + (set-buffer input-buffer) + (erase-buffer) + (insert-file-contents filename) + ;; Run hooks including the uncompression hook. + ;; If they change the file name, then change it for the output also. + (let ((buffer-file-name filename) + (default-major-mode 'emacs-lisp-mode) + (enable-local-eval nil)) + (normal-mode) + (setq filename buffer-file-name))) + (setq byte-compiler-error-flag nil) + ;; It is important that input-buffer not be current at this call, + ;; so that the value of point set in input-buffer + ;; within byte-compile-from-buffer lingers in that buffer. + (setq output-buffer (byte-compile-from-buffer input-buffer filename)) + (if byte-compiler-error-flag + nil + (if byte-compile-verbose + (message "Compiling %s...done" filename)) + (kill-buffer input-buffer) + (save-excursion + (set-buffer output-buffer) + (goto-char (point-max)) + (insert "\n") ; aaah, unix. + (let ((vms-stmlf-recfm t)) + (setq target-file (byte-compile-dest-file filename)) + (or byte-compile-overwrite-file + (condition-case () + (delete-file target-file) + (error nil))) + (if (file-writable-p target-file) + (let ((kanji-flag nil)) ; for nemacs, from Nakagawa Takayuki + (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt)) + (setq buffer-file-type t)) + (write-region 1 (point-max) target-file)) + ;; This is just to give a better error message than write-region + (signal 'file-error + (list "Opening output file" + (if (file-exists-p target-file) + "cannot overwrite file" + "directory not writable or nonexistent") + target-file))) + (or byte-compile-overwrite-file + (condition-case () + (set-file-modes target-file (file-modes filename)) + (error nil)))) + (kill-buffer (current-buffer))) + (if (and byte-compile-generate-call-tree + (or (eq t byte-compile-generate-call-tree) + (y-or-n-p (format "Report call tree for %s? " filename)))) + (save-excursion + (display-call-tree filename))) + (if load + (load target-file)) + t))) + +;; RMS comments the next two out. +(defun byte-compile-and-load-file (&optional filename) + "Compile a file of Lisp code named FILENAME into a file of byte code, +and then load it. The output file's name is made by appending \"c\" to +the end of FILENAME." + (interactive) + (if filename ; I don't get it, (interactive-p) doesn't always work + (byte-compile-file filename t) + (let ((current-prefix-arg '(4))) + (call-interactively 'byte-compile-file)))) + +(defun byte-compile-buffer (&optional buffer) + "Byte-compile and evaluate contents of BUFFER (default: the current buffer)." + (interactive "bByte compile buffer: ") + (setq buffer (if buffer (get-buffer buffer) (current-buffer))) + (message "Compiling %s..." (buffer-name buffer)) + (let* ((filename (or (buffer-file-name buffer) + (concat "#"))) + (byte-compile-current-file buffer)) + (byte-compile-from-buffer buffer filename t)) + (message "Compiling %s...done" (buffer-name buffer)) + t) + +;;; compiling a single function +;;;###autoload +(defun compile-defun (&optional arg) + "Compile and evaluate the current top-level form. +Print the result in the minibuffer. +With argument, insert value in current buffer after the form." + (interactive "P") + (save-excursion + (end-of-defun) + (beginning-of-defun) + (let* ((byte-compile-current-file (buffer-file-name)) + (load-file-name (buffer-file-name)) + (byte-compile-last-warned-form 'nothing) + (value (eval (displaying-byte-compile-warnings + (byte-compile-sexp (read (current-buffer)) + "toplevel forms"))))) + (cond (arg + (message "Compiling from buffer... done.") + (prin1 value (current-buffer)) + (insert "\n")) + ((message "%s" (prin1-to-string value))))))) + +(defvar byte-compile-inbuffer) +(defvar byte-compile-outbuffer) + +(defun byte-compile-from-buffer (byte-compile-inbuffer filename &optional eval) + ;; buffer --> output-buffer, or buffer --> eval form, return nil + (let (byte-compile-outbuffer + ;; Prevent truncation of flonums and lists as we read and print them + (float-output-format nil) + (case-fold-search nil) + (print-length nil) + (print-level nil) + ;; Simulate entry to byte-compile-top-level + (byte-compile-constants nil) + (byte-compile-variables nil) + (byte-compile-tag-number 0) + (byte-compile-depth 0) + (byte-compile-maxdepth 0) + (byte-compile-output nil) + ;; #### This is bound in b-c-close-variables. + ;; (byte-compile-warnings (if (eq byte-compile-warnings t) + ;; byte-compile-warning-types + ;; byte-compile-warnings)) + ) + (byte-compile-close-variables + (save-excursion + (setq byte-compile-outbuffer + (set-buffer (get-buffer-create " *Compiler Output*"))) + (erase-buffer) + ;; (emacs-lisp-mode) + (setq case-fold-search nil) + (and filename + (not eval) + (byte-compile-insert-header filename + byte-compile-inbuffer + byte-compile-outbuffer)) + + ;; This is a kludge. Some operating systems (OS/2, DOS) need to + ;; write files containing binary information specially. + ;; Under most circumstances, such files will be in binary + ;; overwrite mode, so those OS's use that flag to guess how + ;; they should write their data. Advise them that .elc files + ;; need to be written carefully. + (setq overwrite-mode 'overwrite-mode-binary)) + (displaying-byte-compile-warnings + (save-excursion + (set-buffer byte-compile-inbuffer) + (goto-char 1) + + ;; Compile the forms from the input buffer. + (while (progn + (while (progn (skip-chars-forward " \t\n\^l") + (looking-at ";")) + (forward-line 1)) + (not (eobp))) + (byte-compile-file-form (read byte-compile-inbuffer))) + + ;; Compile pending forms at end of file. + (byte-compile-flush-pending) + (byte-compile-warn-about-unresolved-functions) + ;; SHould we always do this? When calling multiple files, it + ;; would be useful to delay this warning until all have + ;; been compiled. + (setq byte-compile-unresolved-functions nil))) + (save-excursion + (set-buffer byte-compile-outbuffer) + (goto-char (point-min)))) + (if (not eval) + byte-compile-outbuffer + (let (form) + (while (condition-case nil + (progn (setq form (read byte-compile-outbuffer)) + t) + (end-of-file nil)) + (eval form))) + (kill-buffer byte-compile-outbuffer) + nil))) + +(defun byte-compile-insert-header (filename byte-compile-inbuffer + byte-compile-outbuffer) + (set-buffer byte-compile-inbuffer) + (let ((dynamic-docstrings byte-compile-dynamic-docstrings)) + (set-buffer byte-compile-outbuffer) + (goto-char 1) + ;; + ;; The magic number of .elc files is ";ELC", or 0x3B454C43. After that is + ;; the file-format version number (19 or 20) as a byte, followed by some + ;; nulls. The primary motivation for doing this is to get some binary + ;; characters up in the first line of the file so that `diff' will simply + ;; say "Binary files differ" instead of actually doing a diff of two .elc + ;; files. An extra benefit is that you can add this to /etc/magic: + ;; + ;; 0 string ;ELC GNU Emacs Lisp compiled file, + ;; >4 byte x version %d + ;; + (insert + ";ELC" + (if (byte-compile-version-cond byte-compile-emacs19-compatibility) 19 20) + "\000\000\000\n" + ) + (insert ";;; compiled by " + (or (and (boundp 'user-mail-address) user-mail-address) + (concat (user-login-name) "@" (system-name))) + " on " + (current-time-string) "\n;;; from file " filename "\n") + (insert ";;; emacs version " emacs-version ".\n") + (insert ";;; bytecomp version " byte-compile-version "\n;;; " + (cond + ((eq byte-optimize 'source) "source-level optimization only") + ((eq byte-optimize 'byte) "byte-level optimization only") + (byte-optimize "optimization is on") + (t "optimization is off")) + (if (byte-compile-version-cond byte-compile-emacs19-compatibility) + "; compiled with Emacs 19 compatibility.\n" + ".\n")) + (if (not (byte-compile-version-cond byte-compile-emacs19-compatibility)) + (insert ";;; this file uses opcodes which do not exist in Emacs 19.\n" + ;; Have to check if emacs-version is bound so that this works + ;; in files loaded early in loadup.el. + "\n(if (and (boundp 'emacs-version)\n" + "\t (or (and (boundp 'epoch::version) epoch::version)\n" + "\t (string-lessp emacs-version \"20\")))\n" + " (error \"`" + ;; prin1-to-string is used to quote backslashes. + (substring (prin1-to-string (file-name-nondirectory filename)) + 1 -1) + "' was compiled for Emacs 20\"))\n\n")) + (insert "(or (boundp 'current-load-list) (setq current-load-list nil))\n" + "\n") + (if (and (byte-compile-version-cond byte-compile-emacs19-compatibility) + dynamic-docstrings) + (insert ";;; this file uses opcodes which do not exist prior to\n" + ";;; XEmacs 19.14/GNU Emacs 19.29 or later." + ;; Have to check if emacs-version is bound so that this works + ;; in files loaded early in loadup.el. + "\n(if (and (boundp 'emacs-version)\n" + "\t (or (and (boundp 'epoch::version) epoch::version)\n" + "\t (and (not (string-match \"XEmacs\" emacs-version))\n" + "\t (string-lessp emacs-version \"19.29\"))\n" + "\t (string-lessp emacs-version \"19.14\")))\n" + " (error \"`" + ;; prin1-to-string is used to quote backslashes. + (substring (prin1-to-string (file-name-nondirectory filename)) + 1 -1) + "' was compiled for XEmacs 19.14/Emacs 19.29 or later\"))\n\n" + ) + )) + + ;; back in the inbuffer; determine and set the coding system for the .elc + ;; file if under Mule. If there are any extended characters in the + ;; input file, use `escape-quoted' to make sure that both binary and + ;; extended characters are output properly and distinguished properly. + ;; Otherwise, use `no-conversion' for maximum portability with non-Mule + ;; Emacsen. + (if (featurep 'mule) + (if (save-excursion + (set-buffer byte-compile-inbuffer) + (goto-char (point-min)) + ;; mrb- There must be a better way than skip-chars-forward + (skip-chars-forward (concat (char-to-string 0) "-" + (char-to-string 255))) + (eq (point) (point-max))) + (setq buffer-file-coding-system 'no-conversion) + (insert "(require 'mule)\n;;;###coding system: escape-quoted\n") + (setq buffer-file-coding-system 'escape-quoted) + ;; Lazy loading not yet implemented for MULE files + ;; mrb - Fix this someday. + (save-excursion + (set-buffer byte-compile-inbuffer) + (setq byte-compile-dynamic nil + byte-compile-dynamic-docstrings nil)) + ;;(external-debugging-output (prin1-to-string (buffer-local-variables)))) + )) + ) + + +(defun byte-compile-output-file-form (form) + ;; writes the given form to the output buffer, being careful of docstrings + ;; in defun, defmacro, defvar, defconst and autoload because make-docfile is + ;; so amazingly stupid. + ;; defalias calls are output directly by byte-compile-file-form-defmumble; + ;; it does not pay to first build the defalias in defmumble and then parse + ;; it here. + (if (and (memq (car-safe form) '(defun defmacro defvar defconst autoload)) + (stringp (nth 3 form))) + (byte-compile-output-docform nil nil '("\n(" 3 ")") form nil + (eq (car form) 'autoload)) + (let ((print-escape-newlines t) + (print-length nil) + (print-level nil) + (print-readably t) ; print #[] for bytecode, 'x for (quote x) + (print-gensym nil)) ; this is too dangerous for now + (princ "\n" byte-compile-outbuffer) + (prin1 form byte-compile-outbuffer) + nil))) + +(defun byte-compile-output-docform (preface name info form specindex quoted) + "Print a form with a doc string. INFO is (prefix doc-index postfix). +If PREFACE and NAME are non-nil, print them too, +before INFO and the FORM but after the doc string itself. +If SPECINDEX is non-nil, it is the index in FORM +of the function bytecode string. In that case, +we output that argument and the following argument (the constants vector) +together, for lazy loading. +QUOTED says that we have to put a quote before the +list that represents a doc string reference. +`autoload' needs that." + ;; We need to examine byte-compile-dynamic-docstrings + ;; in the input buffer (now current), not in the output buffer. + (let ((dynamic-docstrings byte-compile-dynamic-docstrings)) + (set-buffer + (prog1 (current-buffer) + (set-buffer byte-compile-outbuffer) + (let (position) + + ;; Insert the doc string, and make it a comment with #@LENGTH. + (and (>= (nth 1 info) 0) + dynamic-docstrings + (progn + ;; Make the doc string start at beginning of line + ;; for make-docfile's sake. + (insert "\n") + (setq position + (byte-compile-output-as-comment + (nth (nth 1 info) form) nil)) + ;; If the doc string starts with * (a user variable), + ;; negate POSITION. + (if (and (stringp (nth (nth 1 info) form)) + (> (length (nth (nth 1 info) form)) 0) + (char= (aref (nth (nth 1 info) form) 0) ?*)) + (setq position (- position))))) + + (if preface + (progn + (insert preface) + (prin1 name byte-compile-outbuffer))) + (insert (car info)) + (let ((print-escape-newlines t) + (print-readably t) ; print #[] for bytecode, 'x for (quote x) + (print-gensym nil) ; this is too dangerous for now + (index 0)) + (prin1 (car form) byte-compile-outbuffer) + (while (setq form (cdr form)) + (setq index (1+ index)) + (insert " ") + (cond ((and (numberp specindex) (= index specindex)) + (let ((position + (byte-compile-output-as-comment + (cons (car form) (nth 1 form)) + t))) + (princ (format "(#$ . %d) nil" position) + byte-compile-outbuffer) + (setq form (cdr form)) + (setq index (1+ index)))) + ((= index (nth 1 info)) + (if position + (princ (format (if quoted "'(#$ . %d)" "(#$ . %d)") + position) + byte-compile-outbuffer) + (let ((print-escape-newlines nil)) + (goto-char (prog1 (1+ (point)) + (prin1 (car form) + byte-compile-outbuffer))) + (insert "\\\n") + (goto-char (point-max))))) + (t + (prin1 (car form) byte-compile-outbuffer))))) + (insert (nth 2 info)))))) + nil) + +(defvar for-effect) ; ## Kludge! This should be an arg, not a special. + +(defun byte-compile-keep-pending (form &optional handler) + (if (memq byte-optimize '(t source)) + (setq form (byte-optimize-form form t))) + (if handler + (let ((for-effect t)) + ;; To avoid consing up monstrously large forms at load time, we split + ;; the output regularly. + (and (memq (car-safe form) '(fset defalias define-function)) + (nthcdr 300 byte-compile-output) + (byte-compile-flush-pending)) + (funcall handler form) + (if for-effect + (byte-compile-discard))) + (byte-compile-form form t)) + nil) + +(defun byte-compile-flush-pending () + (if byte-compile-output + (let ((form (byte-compile-out-toplevel t 'file))) + (cond ((eq (car-safe form) 'progn) + (mapcar 'byte-compile-output-file-form (cdr form))) + (form + (byte-compile-output-file-form form))) + (setq byte-compile-constants nil + byte-compile-variables nil + byte-compile-depth 0 + byte-compile-maxdepth 0 + byte-compile-output nil)))) + +(defun byte-compile-file-form (form) + (let ((byte-compile-current-form nil) ; close over this for warnings. + handler) + (cond + ((not (consp form)) + (byte-compile-keep-pending form)) + ((and (symbolp (car form)) + (setq handler (get (car form) 'byte-hunk-handler))) + (cond ((setq form (funcall handler form)) + (byte-compile-flush-pending) + (byte-compile-output-file-form form)))) + ((eq form (setq form (macroexpand form byte-compile-macro-environment))) + (byte-compile-keep-pending form)) + (t + (byte-compile-file-form form))))) + +;; Functions and variables with doc strings must be output separately, +;; so make-docfile can recognise them. Most other things can be output +;; as byte-code. + +(put 'defsubst 'byte-hunk-handler 'byte-compile-file-form-defsubst) +(defun byte-compile-file-form-defsubst (form) + (cond ((assq (nth 1 form) byte-compile-unresolved-functions) + (setq byte-compile-current-form (nth 1 form)) + (byte-compile-warn "defsubst %s was used before it was defined" + (nth 1 form)))) + (byte-compile-file-form + (macroexpand form byte-compile-macro-environment)) + ;; Return nil so the form is not output twice. + nil) + +(put 'autoload 'byte-hunk-handler 'byte-compile-file-form-autoload) +(defun byte-compile-file-form-autoload (form) + ;; + ;; If this is an autoload of a macro, and all arguments are constants (that + ;; is, there is no hairy computation going on here) then evaluate the form + ;; at compile-time. This is so that we can make use of macros which we + ;; have autoloaded from the file being compiled. Normal function autoloads + ;; are not automatically evaluated at compile time, because there's not + ;; much point to it (so why bother cluttering up the compile-time namespace.) + ;; + ;; If this is an autoload of a function, then record its definition in the + ;; byte-compile-autoload-environment to suppress any `not known to be + ;; defined' warnings at the end of this file (this only matters for + ;; functions which are autoloaded and compiled in the same file, if the + ;; autoload already exists in the compilation environment, we wouldn't have + ;; warned anyway.) + ;; + (let* ((name (if (byte-compile-constp (nth 1 form)) + (eval (nth 1 form)))) + ;; In v19, the 5th arg to autoload can be t, nil, 'macro, or 'keymap. + (macrop (and (byte-compile-constp (nth 5 form)) + (memq (eval (nth 5 form)) '(t macro)))) +;; (functionp (and (byte-compile-constp (nth 5 form)) +;; (eq 'nil (eval (nth 5 form))))) + ) + (if (and macrop + (let ((form form)) + ;; all forms are constant + (while (if (setq form (cdr form)) + (byte-compile-constp (car form)))) + (null form))) + ;; eval the macro autoload into the compilation enviroment + (eval form)) + + (if name + (let ((old (assq name byte-compile-autoload-environment))) + (cond (old + (if (memq 'redefine byte-compile-warnings) + (byte-compile-warn "multiple autoloads for %s" name)) + (setcdr old form)) + (t + ;; We only use the names in the autoload environment, but + ;; it might be useful to have the bodies some day. + (setq byte-compile-autoload-environment + (cons (cons name form) + byte-compile-autoload-environment))))))) + ;; + ;; Now output the form. + (if (stringp (nth 3 form)) + form + ;; No doc string, so we can compile this as a normal form. + (byte-compile-keep-pending form 'byte-compile-normal-call))) + +(put 'defvar 'byte-hunk-handler 'byte-compile-file-form-defvar) +(put 'defconst 'byte-hunk-handler 'byte-compile-file-form-defvar) +(defun byte-compile-file-form-defvar (form) + (if (> (length form) 4) + (byte-compile-warn "%s used with too many args (%s)" + (car form) (nth 1 form))) + (if (and (> (length form) 3) (not (stringp (nth 3 form)))) + (byte-compile-warn "Third arg to %s %s is not a string: %s" + (car form) (nth 1 form) (nth 3 form))) + (if (null (nth 3 form)) + ;; Since there is no doc string, we can compile this as a normal form, + ;; and not do a file-boundary. + (byte-compile-keep-pending form) + (if (memq 'free-vars byte-compile-warnings) + (setq byte-compile-bound-variables + (cons (cons (nth 1 form) byte-compile-global-bit) + byte-compile-bound-variables))) + (cond ((consp (nth 2 form)) + (setq form (copy-sequence form)) + (setcar (cdr (cdr form)) + (byte-compile-top-level (nth 2 form) nil 'file)))) + + ;; The following turns out not to be necessary, since we emit a call to + ;; defvar, which can hack Vfile_domain by itself! + ;; + ;; If a file domain has been set, emit (put 'VAR 'variable-domain ...) + ;; after this defvar. +; (if byte-compile-file-domain +; (progn +; ;; Actually, this will emit the (put ...) before the (defvar ...) +; ;; but I don't think that can matter in this case. +; (byte-compile-keep-pending +; (list 'put (list 'quote (nth 1 form)) ''variable-domain +; (list 'quote byte-compile-file-domain))))) + form)) + +(put 'require 'byte-hunk-handler 'byte-compile-file-form-eval-boundary) +(defun byte-compile-file-form-eval-boundary (form) + (eval form) + (byte-compile-keep-pending form 'byte-compile-normal-call)) + +(put 'progn 'byte-hunk-handler 'byte-compile-file-form-progn) +(put 'prog1 'byte-hunk-handler 'byte-compile-file-form-progn) +(put 'prog2 'byte-hunk-handler 'byte-compile-file-form-progn) +(defun byte-compile-file-form-progn (form) + (mapcar 'byte-compile-file-form (cdr form)) + ;; Return nil so the forms are not output twice. + nil) + +;; This handler is not necessary, but it makes the output from dont-compile +;; and similar macros cleaner. +(put 'eval 'byte-hunk-handler 'byte-compile-file-form-eval) +(defun byte-compile-file-form-eval (form) + (if (eq (car-safe (nth 1 form)) 'quote) + (nth 1 (nth 1 form)) + (byte-compile-keep-pending form))) + +(put 'defun 'byte-hunk-handler 'byte-compile-file-form-defun) +(defun byte-compile-file-form-defun (form) + (byte-compile-file-form-defmumble form nil)) + +(put 'defmacro 'byte-hunk-handler 'byte-compile-file-form-defmacro) +(defun byte-compile-file-form-defmacro (form) + (byte-compile-file-form-defmumble form t)) + +(defun byte-compile-compiled-obj-to-list (obj) + ;; #### this is fairly disgusting. Rewrite the code instead + ;; so that it doesn't create compiled objects in the first place! + ;; Much better than creating them and then "uncreating" them + ;; like this. + (read (concat "(" + (substring (let ((print-readably t)) + (prin1-to-string obj)) + 2 -1) + ")"))) + +(defun byte-compile-file-form-defmumble (form macrop) + (let* ((name (car (cdr form))) + (this-kind (if macrop 'byte-compile-macro-environment + 'byte-compile-function-environment)) + (that-kind (if macrop 'byte-compile-function-environment + 'byte-compile-macro-environment)) + (this-one (assq name (symbol-value this-kind))) + (that-one (assq name (symbol-value that-kind))) + (byte-compile-free-references nil) + (byte-compile-free-assignments nil)) + + ;; When a function or macro is defined, add it to the call tree so that + ;; we can tell when functions are not used. + (if byte-compile-generate-call-tree + (or (assq name byte-compile-call-tree) + (setq byte-compile-call-tree + (cons (list name nil nil) byte-compile-call-tree)))) + + (setq byte-compile-current-form name) ; for warnings + (if (memq 'redefine byte-compile-warnings) + (byte-compile-arglist-warn form macrop)) + (if byte-compile-verbose + (message "Compiling %s... (%s)" + ;; #### filename used free + (if filename (file-name-nondirectory filename) "") + (nth 1 form))) + (cond (that-one + (if (and (memq 'redefine byte-compile-warnings) + ;; hack hack: don't warn when compiling the stubs in + ;; bytecomp-runtime... + (not (assq (nth 1 form) + byte-compile-initial-macro-environment))) + (byte-compile-warn + "%s defined multiple times, as both function and macro" + (nth 1 form))) + (setcdr that-one nil)) + (this-one + (if (and (memq 'redefine byte-compile-warnings) + ;; hack: don't warn when compiling the magic internal + ;; byte-compiler macros in bytecomp-runtime.el... + (not (assq (nth 1 form) + byte-compile-initial-macro-environment))) + (byte-compile-warn "%s %s defined multiple times in this file" + (if macrop "macro" "function") + (nth 1 form)))) + ((and (fboundp name) + (or (subrp (symbol-function name)) + (eq (car-safe (symbol-function name)) + (if macrop 'lambda 'macro)))) + (if (memq 'redefine byte-compile-warnings) + (byte-compile-warn "%s %s being redefined as a %s" + (if (subrp (symbol-function name)) + "subr" + (if macrop "function" "macro")) + (nth 1 form) + (if macrop "macro" "function"))) + ;; shadow existing definition + (set this-kind + (cons (cons name nil) (symbol-value this-kind)))) + ) + (let ((body (nthcdr 3 form))) + (if (and (stringp (car body)) + (symbolp (car-safe (cdr-safe body))) + (car-safe (cdr-safe body)) + (stringp (car-safe (cdr-safe (cdr-safe body))))) + (byte-compile-warn "Probable `\"' without `\\' in doc string of %s" + (nth 1 form)))) + (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form)))) + (code (byte-compile-byte-code-maker new-one))) + (if this-one + (setcdr this-one new-one) + (set this-kind + (cons (cons name new-one) (symbol-value this-kind)))) + (if (and (stringp (nth 3 form)) + (eq 'quote (car-safe code)) + (eq 'lambda (car-safe (nth 1 code)))) + (cons (car form) + (cons name (cdr (nth 1 code)))) + (byte-compile-flush-pending) + (if (not (stringp (nth 3 form))) + ;; No doc string. Provide -1 as the "doc string index" + ;; so that no element will be treated as a doc string. + (byte-compile-output-docform + "\n(defalias '" + name + (cond ((atom code) + (if macrop '(" '(macro . #[" -1 "])") '(" #[" -1 "]"))) + ((eq (car code) 'quote) + (setq code new-one) + (if macrop '(" '(macro " -1 ")") '(" '(" -1 ")"))) + ((if macrop '(" (cons 'macro (" -1 "))") '(" (" -1 ")")))) + ;; FSF just calls `(append code nil)' here but that relies + ;; on horrible C kludges in concat() that accept byte- + ;; compiled objects and pretend they're vectors. + (if (compiled-function-p code) + (byte-compile-compiled-obj-to-list code) + (append code nil)) + (and (atom code) byte-compile-dynamic + 1) + nil) + ;; Output the form by hand, that's much simpler than having + ;; b-c-output-file-form analyze the defalias. + (byte-compile-output-docform + "\n(defalias '" + name + (cond ((atom code) ; compiled-function-p + (if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]"))) + ((eq (car code) 'quote) + (setq code new-one) + (if macrop '(" '(macro " 2 ")") '(" '(" 2 ")"))) + ((if macrop '(" (cons 'macro (" 5 "))") '(" (" 5 ")")))) + ;; The result of byte-compile-byte-code-maker is either a + ;; compiled-function object, or a list of some kind. If it's + ;; not a cons, we must coerce it into a list of the elements + ;; to be printed to the file. + (if (consp code) + code + (nconc (list + (compiled-function-arglist code) + (compiled-function-instructions code) + (compiled-function-constants code) + (compiled-function-stack-depth code)) + (let ((doc (documentation code t))) + (if doc (list doc))) + (if (commandp code) + (list (nth 1 (compiled-function-interactive code)))))) + (and (atom code) byte-compile-dynamic + 1) + nil)) + (princ ")" byte-compile-outbuffer) + nil)))) + +;; Print Lisp object EXP in the output file, inside a comment, +;; and return the file position it will have. +;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting. +(defun byte-compile-output-as-comment (exp quoted) + (let ((position (point))) + (set-buffer + (prog1 (current-buffer) + (set-buffer byte-compile-outbuffer) + + ;; Insert EXP, and make it a comment with #@LENGTH. + (insert " ") + (if quoted + (prin1 exp byte-compile-outbuffer) + (princ exp byte-compile-outbuffer)) + (goto-char position) + ;; Quote certain special characters as needed. + ;; get_doc_string in doc.c does the unquoting. + (while (search-forward "\^A" nil t) + (replace-match "\^A\^A" t t)) + (goto-char position) + (while (search-forward "\000" nil t) + (replace-match "\^A0" t t)) + (goto-char position) + (while (search-forward "\037" nil t) + (replace-match "\^A_" t t)) + (goto-char (point-max)) + (insert "\037") + (goto-char position) + (insert "#@" (format "%d" (- (point-max) position))) + + ;; Save the file position of the object. + ;; Note we should add 1 to skip the space + ;; that we inserted before the actual doc string, + ;; and subtract 1 to convert from an 1-origin Emacs position + ;; to a file position; they cancel. + (setq position (point)) + (goto-char (point-max)))) + position)) + + + +;; The `domain' declaration. This is legal only at top-level in a file, and +;; should generally be the first form in the file. It is not legal inside +;; function bodies. + +(put 'domain 'byte-hunk-handler 'byte-compile-file-form-domain) +(defun byte-compile-file-form-domain (form) + (if (not (null (cdr (cdr form)))) + (byte-compile-warn "domain used with too many arguments: %s" form)) + (let ((domain (nth 1 form))) + (or (null domain) + (stringp domain) + (progn + (byte-compile-warn + "argument to `domain' declaration must be a literal string: %s" + form) + (setq domain nil))) + (setq byte-compile-file-domain domain)) + (byte-compile-keep-pending form 'byte-compile-normal-call)) + +(defun byte-compile-domain (form) + (byte-compile-warn "The `domain' declaration is legal only at top-level: %s" + (let ((print-escape-newlines t) + (print-level 4) + (print-length 4)) + (prin1-to-string form))) + (byte-compile-normal-call + (list 'signal ''error + (list 'quote (list "`domain' used inside a function" form))))) + +;; This is part of bytecomp.el in 19.35: +(put 'custom-declare-variable 'byte-hunk-handler + 'byte-compile-file-form-custom-declare-variable) +(defun byte-compile-file-form-custom-declare-variable (form) + (if (memq 'free-vars byte-compile-warnings) + (setq byte-compile-bound-variables + (cons (cons (nth 1 (nth 1 form)) + byte-compile-global-bit) + byte-compile-bound-variables))) + form) + + +;;;###autoload +(defun byte-compile (form) + "If FORM is a symbol, byte-compile its function definition. +If FORM is a lambda or a macro, byte-compile it as a function." + (displaying-byte-compile-warnings + (byte-compile-close-variables + (let* ((fun (if (symbolp form) + (and (fboundp form) (symbol-function form)) + form)) + (macro (eq (car-safe fun) 'macro))) + (if macro + (setq fun (cdr fun))) + (cond ((eq (car-safe fun) 'lambda) + (setq fun (if macro + (cons 'macro (byte-compile-lambda fun)) + (byte-compile-lambda fun))) + (if (symbolp form) + (defalias form fun) + fun))))))) + +;;;###autoload +(defun byte-compile-sexp (sexp &optional msg) + "Compile and return SEXP." + (displaying-byte-compile-warnings + (byte-compile-close-variables + (prog1 + (byte-compile-top-level sexp) + (byte-compile-warn-about-unresolved-functions msg))))) + +;; Given a function made by byte-compile-lambda, make a form which produces it. +(defun byte-compile-byte-code-maker (fun) + (cond + ;; ## atom is faster than compiled-func-p. + ((atom fun) ; compiled-function-p + fun) + ;; b-c-lambda didn't produce a compiled-function, so it must be a trivial + ;; function. + ((let (tmp) + (if (and (setq tmp (assq 'byte-code (cdr-safe (cdr fun)))) + (null (cdr (memq tmp fun)))) + ;; Generate a make-byte-code call. + (let* ((interactive (assq 'interactive (cdr (cdr fun))))) + (nconc (list 'make-byte-code + (list 'quote (nth 1 fun)) ;arglist + (nth 1 tmp) ;bytes + (nth 2 tmp) ;consts + (nth 3 tmp)) ;depth + (cond ((stringp (nth 2 fun)) + (list (nth 2 fun))) ;doc + (interactive + (list nil))) + (cond (interactive + (list (if (or (null (nth 1 interactive)) + (stringp (nth 1 interactive))) + (nth 1 interactive) + ;; Interactive spec is a list or a variable + ;; (if it is correct). + (list 'quote (nth 1 interactive)))))))) + ;; a non-compiled function (probably trivial) + (list 'quote fun)))))) + +;; Byte-compile a lambda-expression and return a valid function. +;; The value is usually a compiled function but may be the original +;; lambda-expression. +(defun byte-compile-lambda (fun) + (or (eq 'lambda (car-safe fun)) + (error "not a lambda -- %s" (prin1-to-string fun))) + (let* ((arglist (nth 1 fun)) + (byte-compile-bound-variables + (let ((new-bindings + (mapcar (function (lambda (x) + (cons x byte-compile-arglist-bit))) + (and (memq 'free-vars byte-compile-warnings) + (delq '&rest (delq '&optional + (copy-sequence arglist))))))) + (nconc new-bindings + (cons 'new-scope byte-compile-bound-variables)))) + (body (cdr (cdr fun))) + (doc (if (stringp (car body)) + (prog1 (car body) + (setq body (cdr body))))) + (int (assq 'interactive body))) + (let ((rest arglist)) + (while rest + (cond ((not (symbolp (car rest))) + (byte-compile-warn "non-symbol in arglist: %s" + (prin1-to-string (car rest)))) + ((memq (car rest) '(t nil)) + (byte-compile-warn "constant in arglist: %s" (car rest))) + ((and (char= ?\& (aref (symbol-name (car rest)) 0)) + (not (memq (car rest) '(&optional &rest)))) + (byte-compile-warn "unrecognised `&' keyword in arglist: %s" + (car rest)))) + (setq rest (cdr rest)))) + (cond (int + ;; Skip (interactive) if it is in front (the most usual location). + (if (eq int (car body)) + (setq body (cdr body))) + (cond ((consp (cdr int)) + (if (cdr (cdr int)) + (byte-compile-warn "malformed interactive spec: %s" + (prin1-to-string int))) + ;; If the interactive spec is a call to `list', + ;; don't compile it, because `call-interactively' + ;; looks at the args of `list'. + (let ((form (nth 1 int))) + (while (or (eq (car-safe form) 'let) + (eq (car-safe form) 'let*) + (eq (car-safe form) 'save-excursion)) + (while (consp (cdr form)) + (setq form (cdr form))) + (setq form (car form))) + (or (eq (car-safe form) 'list) + (setq int (list 'interactive + (byte-compile-top-level (nth 1 int))))))) + ((cdr int) + (byte-compile-warn "malformed interactive spec: %s" + (prin1-to-string int)))))) + (let ((compiled (byte-compile-top-level (cons 'progn body) nil 'lambda))) + (if (memq 'unused-vars byte-compile-warnings) + ;; done compiling in this scope, warn now. + (byte-compile-warn-about-unused-variables)) + (if (eq 'byte-code (car-safe compiled)) + (apply 'make-byte-code + (append (list arglist) + ;; byte-string, constants-vector, stack depth + (cdr compiled) + ;; optionally, the doc string. + (if (or doc int) + (list doc)) + ;; optionally, the interactive spec. + (if int + (list (nth 1 int))))) + (setq compiled + (nconc (if int (list int)) + (cond ((eq (car-safe compiled) 'progn) (cdr compiled)) + (compiled (list compiled))))) + (nconc (list 'lambda arglist) + (if (or doc (stringp (car compiled))) + (cons doc (cond (compiled) + (body (list nil)))) + compiled)))))) + +(defun byte-compile-constants-vector () + ;; Builds the constants-vector from the current variables and constants. + ;; This modifies the constants from (const . nil) to (const . offset). + ;; To keep the byte-codes to look up the vector as short as possible: + ;; First 6 elements are vars, as there are one-byte varref codes for those. + ;; Next up to byte-constant-limit are constants, still with one-byte codes. + ;; Next variables again, to get 2-byte codes for variable lookup. + ;; The rest of the constants and variables need 3-byte byte-codes. + (let* ((i -1) + (rest (nreverse byte-compile-variables)) ; nreverse because the first + (other (nreverse byte-compile-constants)) ; vars often are used most. + ret tmp + (limits '(5 ; Use the 1-byte varref codes, + 63 ; 1-constlim ; 1-byte byte-constant codes, + 255 ; 2-byte varref codes, + 65535)) ; 3-byte codes for the rest. + limit) + (while (or rest other) + (setq limit (car limits)) + (while (and rest (not (eq i limit))) + (if (setq tmp (assq (car (car rest)) ret)) + (setcdr (car rest) (cdr tmp)) + (setcdr (car rest) (setq i (1+ i))) + (setq ret (cons (car rest) ret))) + (setq rest (cdr rest))) + (setq limits (cdr limits) + rest (prog1 other + (setq other rest)))) + (apply 'vector (nreverse (mapcar 'car ret))))) + +;; Given an expression FORM, compile it and return an equivalent byte-code +;; expression (a call to the function byte-code). +(defun byte-compile-top-level (form &optional for-effect output-type) + ;; OUTPUT-TYPE advises about how form is expected to be used: + ;; 'eval or nil -> a single form, + ;; 'progn or t -> a list of forms, + ;; 'lambda -> body of a lambda, + ;; 'file -> used at file-level. + (let ((byte-compile-constants nil) + (byte-compile-variables nil) + (byte-compile-tag-number 0) + (byte-compile-depth 0) + (byte-compile-maxdepth 0) + (byte-compile-output nil)) + (if (memq byte-optimize '(t source)) + (setq form (byte-optimize-form form for-effect))) + (while (and (eq (car-safe form) 'progn) (null (cdr (cdr form)))) + (setq form (nth 1 form))) + (if (and (eq 'byte-code (car-safe form)) + (not (memq byte-optimize '(t byte))) + (stringp (nth 1 form)) + (vectorp (nth 2 form)) + (natnump (nth 3 form))) + form + (byte-compile-form form for-effect) + (byte-compile-out-toplevel for-effect output-type)))) + +(defun byte-compile-out-toplevel (&optional for-effect output-type) + (if for-effect + ;; The stack is empty. Push a value to be returned from (byte-code ..). + (if (eq (car (car byte-compile-output)) 'byte-discard) + (setq byte-compile-output (cdr byte-compile-output)) + (byte-compile-push-constant + ;; Push any constant - preferably one which already is used, and + ;; a number or symbol - ie not some big sequence. The return value + ;; isn't returned, but it would be a shame if some textually large + ;; constant was not optimized away because we chose to return it. + (and (not (assq nil byte-compile-constants)) ; Nil is often there. + (let ((tmp (reverse byte-compile-constants))) + (while (and tmp (not (or (symbolp (car (car tmp))) + (numberp (car (car tmp)))))) + (setq tmp (cdr tmp))) + (car (car tmp))))))) + (byte-compile-out 'byte-return 0) + (setq byte-compile-output (nreverse byte-compile-output)) + (if (memq byte-optimize '(t byte)) + (setq byte-compile-output + (byte-optimize-lapcode byte-compile-output for-effect))) + + ;; Decompile trivial functions: + ;; only constants and variables, or a single funcall except in lambdas. + ;; Except for Lisp_Compiled objects, forms like (foo "hi") + ;; are still quicker than (byte-code "..." [foo "hi"] 2). + ;; Note that even (quote foo) must be parsed just as any subr by the + ;; interpreter, so quote should be compiled into byte-code in some contexts. + ;; What to leave uncompiled: + ;; lambda -> never. we used to leave it uncompiled if the body was + ;; a single atom, but that causes confusion if the docstring + ;; uses the (file . pos) syntax. Besides, now that we have + ;; the Lisp_Compiled type, the compiled form is faster. + ;; eval -> atom, quote or (function atom atom atom) + ;; progn -> as <> or (progn <> atom) + ;; file -> as progn, but takes both quotes and atoms, and longer forms. + (let (rest + (maycall (not (eq output-type 'lambda))) ; t if we may make a funcall. + tmp body) + (cond + ;; #### This should be split out into byte-compile-nontrivial-function-p. + ((or (eq output-type 'lambda) + (nthcdr (if (eq output-type 'file) 50 8) byte-compile-output) + (assq 'TAG byte-compile-output) ; Not necessary, but speeds up a bit. + (not (setq tmp (assq 'byte-return byte-compile-output))) + (progn + (setq rest (nreverse + (cdr (memq tmp (reverse byte-compile-output))))) + (while (cond + ((memq (car (car rest)) '(byte-varref byte-constant)) + (setq tmp (car (cdr (car rest)))) + (if (if (eq (car (car rest)) 'byte-constant) + (or (consp tmp) + (and (symbolp tmp) + (not (keywordp tmp)) + (not (memq tmp '(nil t)))))) + (if maycall + (setq body (cons (list 'quote tmp) body))) + (setq body (cons tmp body)))) + ((and maycall + ;; Allow a funcall if at most one atom follows it. + (null (nthcdr 3 rest)) + (setq tmp + ;; XEmacs change for rms funs + (or (and + (byte-compile-version-cond + byte-compile-emacs19-compatibility) + (get (car (car rest)) + 'byte-opcode19-invert)) + (get (car (car rest)) + 'byte-opcode-invert))) + (or (null (cdr rest)) + (and (memq output-type '(file progn t)) + (cdr (cdr rest)) + (eq (car (nth 1 rest)) 'byte-discard) + (progn (setq rest (cdr rest)) t)))) + (setq maycall nil) ; Only allow one real function call. + (setq body (nreverse body)) + (setq body (list + (if (and (eq tmp 'funcall) + (eq (car-safe (car body)) 'quote)) + (cons (nth 1 (car body)) (cdr body)) + (cons tmp body)))) + (or (eq output-type 'file) + (not (delq nil (mapcar 'consp (cdr (car body)))))))) + (setq rest (cdr rest))) + rest)) + (let ((byte-compile-vector (byte-compile-constants-vector))) + (list 'byte-code (byte-compile-lapcode byte-compile-output) + byte-compile-vector byte-compile-maxdepth))) + ;; it's a trivial function + ((cdr body) (cons 'progn (nreverse body))) + ((car body))))) + +;; Given BODY, compile it and return a new body. +(defun byte-compile-top-level-body (body &optional for-effect) + (setq body (byte-compile-top-level (cons 'progn body) for-effect t)) + (cond ((eq (car-safe body) 'progn) + (cdr body)) + (body + (list body)))) + +;; This is the recursive entry point for compiling each subform of an +;; expression. +;; If for-effect is non-nil, byte-compile-form will output a byte-discard +;; before terminating (ie no value will be left on the stack). +;; A byte-compile handler may, when for-effect is non-nil, choose output code +;; which does not leave a value on the stack, and then set for-effect to nil +;; (to prevent byte-compile-form from outputting the byte-discard). +;; If a handler wants to call another handler, it should do so via +;; byte-compile-form, or take extreme care to handle for-effect correctly. +;; (Use byte-compile-form-do-effect to reset the for-effect flag too.) +;; +(defun byte-compile-form (form &optional for-effect) + (setq form (macroexpand form byte-compile-macro-environment)) + (cond ((not (consp form)) + ;; XEmacs addition: keywordp + (cond ((or (not (symbolp form)) (keywordp form) (memq form '(nil t))) + (byte-compile-constant form)) + ((and for-effect byte-compile-delete-errors) + (setq for-effect nil)) + (t (byte-compile-variable-ref 'byte-varref form)))) + ((symbolp (car form)) + (let* ((fn (car form)) + (handler (get fn 'byte-compile))) + (if (memq fn '(t nil)) + (byte-compile-warn "%s called as a function" fn)) + (if (and handler + (or (not (byte-compile-version-cond + byte-compile-emacs19-compatibility)) + (not (get (get fn 'byte-opcode) 'emacs20-opcode)))) + (funcall handler form) + (if (memq 'callargs byte-compile-warnings) + (byte-compile-callargs-warn form)) + (byte-compile-normal-call form)))) + ((and (or (compiled-function-p (car form)) + (eq (car-safe (car form)) 'lambda)) + ;; if the form comes out the same way it went in, that's + ;; because it was malformed, and we couldn't unfold it. + (not (eq form (setq form (byte-compile-unfold-lambda form))))) + (byte-compile-form form for-effect) + (setq for-effect nil)) + ((byte-compile-normal-call form))) + (if for-effect + (byte-compile-discard))) + +(defun byte-compile-normal-call (form) + (if byte-compile-generate-call-tree + (byte-compile-annotate-call-tree form)) + (byte-compile-push-constant (car form)) + (mapcar 'byte-compile-form (cdr form)) ; wasteful, but faster. + (byte-compile-out 'byte-call (length (cdr form)))) + +;; kludge added to XEmacs to work around the bogosities of a nonlexical lisp. +(or (fboundp 'globally-boundp) (fset 'globally-boundp 'boundp)) + +(defun byte-compile-variable-ref (base-op var &optional varbind-flags) + (if (or (not (symbolp var)) (keywordp var) (memq var '(nil t))) + (byte-compile-warn (if (eq base-op 'byte-varbind) + "Attempt to let-bind %s %s" + "Variable reference to %s %s") + (if (symbolp var) "constant" "nonvariable") + (prin1-to-string var)) + (if (and (get var 'byte-obsolete-variable) + (memq 'obsolete byte-compile-warnings)) + (let ((ob (get var 'byte-obsolete-variable))) + (byte-compile-warn "%s is an obsolete variable; %s" var + (if (stringp ob) + ob + (format "use %s instead." ob))))) + (if (and (get var 'byte-compatible-variable) + (memq 'pedantic byte-compile-warnings)) + (let ((ob (get var 'byte-compatible-variable))) + (byte-compile-warn "%s is provided for compatibility; %s" var + (if (stringp ob) + ob + (format "use %s instead." ob))))) + (if (memq 'free-vars byte-compile-warnings) + (if (eq base-op 'byte-varbind) + (setq byte-compile-bound-variables + (cons (cons var (or varbind-flags 0)) + byte-compile-bound-variables)) + (or (globally-boundp var) + (let ((cell (assq var byte-compile-bound-variables))) + (if cell (setcdr cell + (logior (cdr cell) + (if (eq base-op 'byte-varset) + byte-compile-assigned-bit + byte-compile-referenced-bit))))) + (if (eq base-op 'byte-varset) + (or (memq var byte-compile-free-assignments) + (progn + (byte-compile-warn "assignment to free variable %s" + var) + (setq byte-compile-free-assignments + (cons var byte-compile-free-assignments)))) + (or (memq var byte-compile-free-references) + (progn + (byte-compile-warn "reference to free variable %s" var) + (setq byte-compile-free-references + (cons var byte-compile-free-references))))))))) + (let ((tmp (assq var byte-compile-variables))) + (or tmp + (setq tmp (list var) + byte-compile-variables (cons tmp byte-compile-variables))) + (byte-compile-out base-op tmp))) + +(defmacro byte-compile-get-constant (const) + (` (or (if (stringp (, const)) + (assoc (, const) byte-compile-constants) + (assq (, const) byte-compile-constants)) + (car (setq byte-compile-constants + (cons (list (, const)) byte-compile-constants)))))) + +;; Use this when the value of a form is a constant. This obeys for-effect. +(defun byte-compile-constant (const) + (if for-effect + (setq for-effect nil) + (byte-compile-out 'byte-constant (byte-compile-get-constant const)))) + +;; Use this for a constant that is not the value of its containing form. +;; This ignores for-effect. +(defun byte-compile-push-constant (const) + (let ((for-effect nil)) + (inline (byte-compile-constant const)))) + + +;; Compile those primitive ordinary functions +;; which have special byte codes just for speed. + +(defmacro byte-defop-compiler (function &optional compile-handler) + ;; add a compiler-form for FUNCTION. + ;; If function is a symbol, then the variable "byte-SYMBOL" must name + ;; the opcode to be used. If function is a list, the first element + ;; is the function and the second element is the bytecode-symbol. + ;; COMPILE-HANDLER is the function to use to compile this byte-op, or + ;; may be the abbreviations 0, 1, 2, 3, 0-1, 1-2, 2-3, 0+1, 1+1, 2+1, + ;; 0-1+1, 1-2+1, 2-3+1, 0+2, or 1+2. If it is nil, then the handler is + ;; "byte-compile-SYMBOL." + (let (opcode) + (if (symbolp function) + (setq opcode (intern (concat "byte-" (symbol-name function)))) + (setq opcode (car (cdr function)) + function (car function))) + (let ((fnform + (list 'put (list 'quote function) ''byte-compile + (list 'quote + (or (cdr (assq compile-handler + '((0 . byte-compile-no-args) + (1 . byte-compile-one-arg) + (2 . byte-compile-two-args) + (3 . byte-compile-three-args) + (0-1 . byte-compile-zero-or-one-arg) + (1-2 . byte-compile-one-or-two-args) + (2-3 . byte-compile-two-or-three-args) + (0+1 . byte-compile-no-args-with-one-extra) + (1+1 . byte-compile-one-arg-with-one-extra) + (2+1 . byte-compile-two-args-with-one-extra) + (0-1+1 . byte-compile-zero-or-one-arg-with-one-extra) + (1-2+1 . byte-compile-one-or-two-args-with-one-extra) + (2-3+1 . byte-compile-two-or-three-args-with-one-extra) + (0+2 . byte-compile-no-args-with-two-extra) + (1+2 . byte-compile-one-arg-with-two-extra) + + ))) + compile-handler + (intern (concat "byte-compile-" + (symbol-name function)))))))) + (if opcode + (list 'progn fnform + (list 'put (list 'quote function) + ''byte-opcode (list 'quote opcode)) + (list 'put (list 'quote opcode) + ''byte-opcode-invert (list 'quote function))) + fnform)))) + +(defmacro byte-defop-compiler20 (function &optional compile-handler) + ;; Just like byte-defop-compiler, but defines an opcode that will only + ;; be used when byte-compile-emacs19-compatibility is false. + (if (and (byte-compile-single-version) + byte-compile-emacs19-compatibility) + ;; #### instead of doing nothing, this should do some remprops, + ;; #### to protect against the case where a single-version compiler + ;; #### is loaded into a world that has contained a multi-version one. + nil + (list 'progn + (list 'put + (list 'quote + (or (car (cdr-safe function)) + (intern (concat "byte-" + (symbol-name (or (car-safe function) function)))))) + ''emacs20-opcode t) + (list 'byte-defop-compiler function compile-handler)))) + +;; XEmacs addition: +(defmacro byte-defop-compiler-rmsfun (function &optional compile-handler) + ;; for functions like `eq' that compile into different opcodes depending + ;; on the Emacs version: byte-old-eq for v19, byte-eq for v20. + (let ((opcode (intern (concat "byte-" (symbol-name function)))) + (opcode19 (intern (concat "byte-old-" (symbol-name function)))) + (fnform + (list 'put (list 'quote function) ''byte-compile + (list 'quote + (or (cdr (assq compile-handler + '((2 . byte-compile-two-args-19->20) + ))) + compile-handler + (intern (concat "byte-compile-" + (symbol-name function)))))))) + (list 'progn fnform + (list 'put (list 'quote function) + ''byte-opcode (list 'quote opcode)) + (list 'put (list 'quote function) + ''byte-opcode19 (list 'quote opcode19)) + (list 'put (list 'quote opcode) + ''byte-opcode-invert (list 'quote function)) + (list 'put (list 'quote opcode19) + ''byte-opcode19-invert (list 'quote function))))) + +(defmacro byte-defop-compiler-1 (function &optional compile-handler) + (list 'byte-defop-compiler (list function nil) compile-handler)) + + +(put 'byte-call 'byte-opcode-invert 'funcall) +(put 'byte-list1 'byte-opcode-invert 'list) +(put 'byte-list2 'byte-opcode-invert 'list) +(put 'byte-list3 'byte-opcode-invert 'list) +(put 'byte-list4 'byte-opcode-invert 'list) +(put 'byte-listN 'byte-opcode-invert 'list) +(put 'byte-concat2 'byte-opcode-invert 'concat) +(put 'byte-concat3 'byte-opcode-invert 'concat) +(put 'byte-concat4 'byte-opcode-invert 'concat) +(put 'byte-concatN 'byte-opcode-invert 'concat) +(put 'byte-insertN 'byte-opcode-invert 'insert) + +(byte-defop-compiler (dot byte-point) 0+1) +(byte-defop-compiler (dot-max byte-point-max) 0+1) +(byte-defop-compiler (dot-min byte-point-min) 0+1) +(byte-defop-compiler point 0+1) +(byte-defop-compiler-rmsfun eq 2) +(byte-defop-compiler point-max 0+1) +(byte-defop-compiler point-min 0+1) +(byte-defop-compiler following-char 0+1) +(byte-defop-compiler preceding-char 0+1) +(byte-defop-compiler current-column 0+1) +;; FSF has special function here; generalized here by the 1+2 stuff. +(byte-defop-compiler (indent-to-column byte-indent-to) 1+2) +(byte-defop-compiler indent-to 1+2) +(byte-defop-compiler-rmsfun equal 2) +(byte-defop-compiler eolp 0+1) +(byte-defop-compiler eobp 0+1) +(byte-defop-compiler bolp 0+1) +(byte-defop-compiler bobp 0+1) +(byte-defop-compiler current-buffer 0) +;;(byte-defop-compiler read-char 0) ;; obsolete +(byte-defop-compiler-rmsfun memq 2) +(byte-defop-compiler interactive-p 0) +(byte-defop-compiler widen 0+1) +(byte-defop-compiler end-of-line 0-1+1) +(byte-defop-compiler forward-char 0-1+1) +(byte-defop-compiler forward-line 0-1+1) +(byte-defop-compiler symbolp 1) +(byte-defop-compiler consp 1) +(byte-defop-compiler stringp 1) +(byte-defop-compiler listp 1) +(byte-defop-compiler not 1) +(byte-defop-compiler (null byte-not) 1) +(byte-defop-compiler car 1) +(byte-defop-compiler cdr 1) +(byte-defop-compiler length 1) +(byte-defop-compiler symbol-value 1) +(byte-defop-compiler symbol-function 1) +(byte-defop-compiler (1+ byte-add1) 1) +(byte-defop-compiler (1- byte-sub1) 1) +(byte-defop-compiler goto-char 1+1) +(byte-defop-compiler char-after 0-1+1) +(byte-defop-compiler set-buffer 1) +;;(byte-defop-compiler set-mark 1) ;; obsolete +(byte-defop-compiler forward-word 1+1) +(byte-defop-compiler char-syntax 1+1) +(byte-defop-compiler nreverse 1) +(byte-defop-compiler car-safe 1) +(byte-defop-compiler cdr-safe 1) +(byte-defop-compiler numberp 1) +(byte-defop-compiler integerp 1) +(byte-defop-compiler skip-chars-forward 1-2+1) +(byte-defop-compiler skip-chars-backward 1-2+1) +(byte-defop-compiler (eql byte-eq) 2) +(byte-defop-compiler20 old-eq 2) +(byte-defop-compiler20 old-memq 2) +(byte-defop-compiler cons 2) +(byte-defop-compiler aref 2) +(byte-defop-compiler (= byte-eqlsign) 2) +(byte-defop-compiler (< byte-lss) 2) +(byte-defop-compiler (> byte-gtr) 2) +(byte-defop-compiler (<= byte-leq) 2) +(byte-defop-compiler (>= byte-geq) 2) +(byte-defop-compiler get 2+1) +(byte-defop-compiler nth 2) +(byte-defop-compiler substring 2-3) +(byte-defop-compiler (move-marker byte-set-marker) 2-3) +(byte-defop-compiler set-marker 2-3) +(byte-defop-compiler match-beginning 1) +(byte-defop-compiler match-end 1) +(byte-defop-compiler upcase 1+1) +(byte-defop-compiler downcase 1+1) +(byte-defop-compiler string= 2) +(byte-defop-compiler string< 2) +(byte-defop-compiler (string-equal byte-string=) 2) +(byte-defop-compiler (string-lessp byte-string<) 2) +(byte-defop-compiler20 old-equal 2) +(byte-defop-compiler nthcdr 2) +(byte-defop-compiler elt 2) +(byte-defop-compiler20 old-member 2) +(byte-defop-compiler20 old-assq 2) +(byte-defop-compiler (rplaca byte-setcar) 2) +(byte-defop-compiler (rplacd byte-setcdr) 2) +(byte-defop-compiler setcar 2) +(byte-defop-compiler setcdr 2) +;; buffer-substring now has its own function. This used to be +;; 2+1, but now all args are optional. +(byte-defop-compiler buffer-substring) +(byte-defop-compiler delete-region 2+1) +(byte-defop-compiler narrow-to-region 2+1) +(byte-defop-compiler (% byte-rem) 2) +(byte-defop-compiler aset 3) + +(byte-defop-compiler-rmsfun member 2) +(byte-defop-compiler-rmsfun assq 2) + +(byte-defop-compiler max byte-compile-associative) +(byte-defop-compiler min byte-compile-associative) +(byte-defop-compiler (+ byte-plus) byte-compile-associative) +(byte-defop-compiler (* byte-mult) byte-compile-associative) + +;;####(byte-defop-compiler move-to-column 1) +(byte-defop-compiler-1 interactive byte-compile-noop) +(byte-defop-compiler-1 domain byte-compile-domain) + +;; As of GNU Emacs 19.18 and Lucid Emacs 19.8, mod and % are different: `%' +;; means integral remainder and may have a negative result; `mod' is always +;; positive, and accepts floating point args. All code which uses `mod' and +;; requires the new interpretation must be compiled with bytecomp version 2.18 +;; or newer, or the emitted code will run the byte-code for `%' instead of an +;; actual call to `mod'. So be careful of compiling new code with an old +;; compiler. Note also that `%' is more efficient than `mod' because the +;; former is byte-coded and the latter is not. +;;(byte-defop-compiler (mod byte-rem) 2) + + +(defun byte-compile-subr-wrong-args (form n) + (byte-compile-warn "%s called with %d arg%s, but requires %s" + (car form) (length (cdr form)) + (if (= 1 (length (cdr form))) "" "s") n) + ;; get run-time wrong-number-of-args error. + (byte-compile-normal-call form)) + +(defun byte-compile-no-args (form) + (if (not (= (length form) 1)) + (byte-compile-subr-wrong-args form "none") + (byte-compile-out (get (car form) 'byte-opcode) 0))) + +(defun byte-compile-one-arg (form) + (if (not (= (length form) 2)) + (byte-compile-subr-wrong-args form 1) + (byte-compile-form (car (cdr form))) ;; Push the argument + (byte-compile-out (get (car form) 'byte-opcode) 0))) + +(defun byte-compile-two-args (form) + (if (not (= (length form) 3)) + (byte-compile-subr-wrong-args form 2) + (byte-compile-form (car (cdr form))) ;; Push the arguments + (byte-compile-form (nth 2 form)) + (byte-compile-out (get (car form) 'byte-opcode) 0))) + +(defun byte-compile-three-args (form) + (if (not (= (length form) 4)) + (byte-compile-subr-wrong-args form 3) + (byte-compile-form (car (cdr form))) ;; Push the arguments + (byte-compile-form (nth 2 form)) + (byte-compile-form (nth 3 form)) + (byte-compile-out (get (car form) 'byte-opcode) 0))) + +(defun byte-compile-zero-or-one-arg (form) + (let ((len (length form))) + (cond ((= len 1) (byte-compile-one-arg (append form '(nil)))) + ((= len 2) (byte-compile-one-arg form)) + (t (byte-compile-subr-wrong-args form "0-1"))))) + +(defun byte-compile-one-or-two-args (form) + (let ((len (length form))) + (cond ((= len 2) (byte-compile-two-args (append form '(nil)))) + ((= len 3) (byte-compile-two-args form)) + (t (byte-compile-subr-wrong-args form "1-2"))))) + +(defun byte-compile-two-or-three-args (form) + (let ((len (length form))) + (cond ((= len 3) (byte-compile-three-args (append form '(nil)))) + ((= len 4) (byte-compile-three-args form)) + (t (byte-compile-subr-wrong-args form "2-3"))))) + +;; from Ben Wing : some inlined functions have extra +;; optional args added to them in XEmacs 19.12. Changing the byte +;; interpreter to deal with these args would be wrong and cause +;; incompatibility, so we generate non-inlined calls for those cases. +;; Without the following functions, spurious warnings will be generated; +;; however, they would still compile correctly because +;; `byte-compile-subr-wrong-args' also converts the call to non-inlined. + +(defun byte-compile-no-args-with-one-extra (form) + (let ((len (length form))) + (cond ((= len 1) (byte-compile-no-args form)) + ((= len 2) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "0-1"))))) + +(defun byte-compile-one-arg-with-one-extra (form) + (let ((len (length form))) + (cond ((= len 2) (byte-compile-one-arg form)) + ((= len 3) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "1-2"))))) + +(defun byte-compile-two-args-with-one-extra (form) + (let ((len (length form))) + (cond ((= len 3) (byte-compile-two-args form)) + ((= len 4) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "2-3"))))) + +(defun byte-compile-zero-or-one-arg-with-one-extra (form) + (let ((len (length form))) + (cond ((= len 1) (byte-compile-one-arg (append form '(nil)))) + ((= len 2) (byte-compile-one-arg form)) + ((= len 3) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "0-2"))))) + +(defun byte-compile-one-or-two-args-with-one-extra (form) + (let ((len (length form))) + (cond ((= len 2) (byte-compile-two-args (append form '(nil)))) + ((= len 3) (byte-compile-two-args form)) + ((= len 4) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "1-3"))))) + +(defun byte-compile-two-or-three-args-with-one-extra (form) + (let ((len (length form))) + (cond ((= len 3) (byte-compile-three-args (append form '(nil)))) + ((= len 4) (byte-compile-three-args form)) + ((= len 5) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "2-4"))))) + +(defun byte-compile-no-args-with-two-extra (form) + (let ((len (length form))) + (cond ((= len 1) (byte-compile-no-args form)) + ((or (= len 2) (= len 3)) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "0-2"))))) + +(defun byte-compile-one-arg-with-two-extra (form) + (let ((len (length form))) + (cond ((= len 2) (byte-compile-one-arg form)) + ((or (= len 3) (= len 4)) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "1-3"))))) + +;; XEmacs: used for functions that have a different opcode in v19 than v20. +;; this includes `eq', `equal', and other old-ified functions. +(defun byte-compile-two-args-19->20 (form) + (if (not (= (length form) 3)) + (byte-compile-subr-wrong-args form 2) + (byte-compile-form (car (cdr form))) ;; Push the arguments + (byte-compile-form (nth 2 form)) + (if (byte-compile-version-cond byte-compile-emacs19-compatibility) + (byte-compile-out (get (car form) 'byte-opcode19) 0) + (byte-compile-out (get (car form) 'byte-opcode) 0)))) + +(defun byte-compile-noop (form) + (byte-compile-constant nil)) + +(defun byte-compile-discard () + (byte-compile-out 'byte-discard 0)) + + +;; Compile a function that accepts one or more args and is right-associative. +;; We do it by left-associativity so that the operations +;; are done in the same order as in interpreted code. +(defun byte-compile-associative (form) + (if (cdr form) + (let ((opcode (get (car form) 'byte-opcode)) + (args (copy-sequence (cdr form)))) + (byte-compile-form (car args)) + (setq args (cdr args)) + (while args + (byte-compile-form (car args)) + (byte-compile-out opcode 0) + (setq args (cdr args)))) + (byte-compile-constant (eval form)))) + + +;; more complicated compiler macros + +(byte-defop-compiler list) +(byte-defop-compiler concat) +(byte-defop-compiler fset) +(byte-defop-compiler insert) +(byte-defop-compiler-1 function byte-compile-function-form) +(byte-defop-compiler-1 - byte-compile-minus) +(byte-defop-compiler (/ byte-quo) byte-compile-quo) +(byte-defop-compiler nconc) +(byte-defop-compiler-1 beginning-of-line) + +(defun byte-compile-buffer-substring (form) + (let ((len (length form))) + ;; buffer-substring used to take exactly two args, but now takes 0-3. + ;; convert 0-2 to two args and use special bytecode operand. + ;; convert 3 args to a normal call. + (cond ((= len 1) (setq form (append form '(nil nil))) + (= len 2) (setq form (append form '(nil))))) + (cond ((= len 3) (byte-compile-two-args form)) + ((= len 4) (byte-compile-normal-call form)) + (t (byte-compile-subr-wrong-args form "0-3"))))) + +(defun byte-compile-list (form) + (let ((count (length (cdr form)))) + (cond ((= count 0) + (byte-compile-constant nil)) + ((< count 5) + (mapcar 'byte-compile-form (cdr form)) + (byte-compile-out + (aref [byte-list1 byte-list2 byte-list3 byte-list4] (1- count)) 0)) + ((< count 256) + (mapcar 'byte-compile-form (cdr form)) + (byte-compile-out 'byte-listN count)) + (t (byte-compile-normal-call form))))) + +(defun byte-compile-concat (form) + (let ((count (length (cdr form)))) + (cond ((and (< 1 count) (< count 5)) + (mapcar 'byte-compile-form (cdr form)) + (byte-compile-out + (aref [byte-concat2 byte-concat3 byte-concat4] (- count 2)) + 0)) + ;; Concat of one arg is not a no-op if arg is not a string. + ((= count 0) + (byte-compile-form "")) + ((< count 256) + (mapcar 'byte-compile-form (cdr form)) + (byte-compile-out 'byte-concatN count)) + ((byte-compile-normal-call form))))) + +(defun byte-compile-minus (form) + (if (null (setq form (cdr form))) + (byte-compile-constant 0) + (byte-compile-form (car form)) + (if (cdr form) + (while (setq form (cdr form)) + (byte-compile-form (car form)) + (byte-compile-out 'byte-diff 0)) + (byte-compile-out 'byte-negate 0)))) + +(defun byte-compile-quo (form) + (let ((len (length form))) + (cond ((<= len 2) + (byte-compile-subr-wrong-args form "2 or more")) + (t + (byte-compile-form (car (setq form (cdr form)))) + (while (setq form (cdr form)) + (byte-compile-form (car form)) + (byte-compile-out 'byte-quo 0)))))) + +(defun byte-compile-nconc (form) + (let ((len (length form))) + (cond ((= len 1) + (byte-compile-constant nil)) + ((= len 2) + ;; nconc of one arg is a noop, even if that arg isn't a list. + (byte-compile-form (nth 1 form))) + (t + (byte-compile-form (car (setq form (cdr form)))) + (while (setq form (cdr form)) + (byte-compile-form (car form)) + (byte-compile-out 'byte-nconc 0)))))) + +(defun byte-compile-fset (form) + ;; warn about forms like (fset 'foo '(lambda () ...)) + ;; (where the lambda expression is non-trivial...) + ;; Except don't warn if the first argument is 'make-byte-code, because + ;; I'm sick of getting mail asking me whether that warning is a problem. + (let ((fn (nth 2 form)) + body) + (if (and (eq (car-safe fn) 'quote) + (eq (car-safe (setq fn (nth 1 fn))) 'lambda) + (not (eq (car-safe (cdr-safe (nth 1 form))) 'make-byte-code))) + (progn + (setq body (cdr (cdr fn))) + (if (stringp (car body)) (setq body (cdr body))) + (if (eq 'interactive (car-safe (car body))) (setq body (cdr body))) + (if (and (consp (car body)) + (not (eq 'byte-code (car (car body))))) + (byte-compile-warn + "A quoted lambda form is the second argument of fset. This is probably + not what you want, as that lambda cannot be compiled. Consider using + the syntax (function (lambda (...) ...)) instead."))))) + (byte-compile-two-args form)) + +(defun byte-compile-funarg (form) + ;; (mapcar '(lambda (x) ..) ..) ==> (mapcar (function (lambda (x) ..)) ..) + ;; for cases where it's guaranteed that first arg will be used as a lambda. + (byte-compile-normal-call + (let ((fn (nth 1 form))) + (if (and (eq (car-safe fn) 'quote) + (eq (car-safe (nth 1 fn)) 'lambda)) + (cons (car form) + (cons (cons 'function (cdr fn)) + (cdr (cdr form)))) + form)))) + +;; (function foo) must compile like 'foo, not like (symbol-function 'foo). +;; Otherwise it will be incompatible with the interpreter, +;; and (funcall (function foo)) will lose with autoloads. + +(defun byte-compile-function-form (form) + (byte-compile-constant + (cond ((symbolp (nth 1 form)) + (nth 1 form)) + ((byte-compile-lambda (nth 1 form)))))) + +(defun byte-compile-insert (form) + (cond ((null (cdr form)) + (byte-compile-constant nil)) + ((<= (length form) 256) + (mapcar 'byte-compile-form (cdr form)) + (if (cdr (cdr form)) + (byte-compile-out 'byte-insertN (length (cdr form))) + (byte-compile-out 'byte-insert 0))) + ((memq t (mapcar 'consp (cdr (cdr form)))) + (byte-compile-normal-call form)) + ;; We can split it; there is no function call after inserting 1st arg. + (t + (while (setq form (cdr form)) + (byte-compile-form (car form)) + (byte-compile-out 'byte-insert 0) + (if (cdr form) + (byte-compile-discard)))))) + +;; alas, the old (pre-19.12, and all existing versions of FSFmacs 19) +;; byte compiler will generate incorrect code for +;; (beginning-of-line nil buffer) because it buggily doesn't +;; check the number of arguments passed to beginning-of-line. + +(defun byte-compile-beginning-of-line (form) + (let ((len (length form))) + (cond ((> len 3) + (byte-compile-subr-wrong-args form "0-2")) + ((or (= len 3) (not (byte-compile-constp (nth 1 form)))) + (byte-compile-normal-call form)) + (t + (byte-compile-form + (list 'forward-line + (if (integerp (setq form (or (eval (nth 1 form)) 1))) + (1- form) + (byte-compile-warn + "Non-numeric arg to beginning-of-line: %s" form) + (list '1- (list 'quote form)))) + t) + (byte-compile-constant nil))))) + + +(byte-defop-compiler set) +(byte-defop-compiler-1 setq) +(byte-defop-compiler-1 set-default) +(byte-defop-compiler-1 setq-default) + +(byte-defop-compiler-1 quote) +(byte-defop-compiler-1 quote-form) + +(defun byte-compile-setq (form) + (let ((args (cdr form))) + (if args + (while args + (byte-compile-form (car (cdr args))) + (or for-effect (cdr (cdr args)) + (byte-compile-out 'byte-dup 0)) + (byte-compile-variable-ref 'byte-varset (car args)) + (setq args (cdr (cdr args)))) + ;; (setq), with no arguments. + (byte-compile-form nil for-effect)) + (setq for-effect nil))) + +(defun byte-compile-set (form) + ;; Compile (set 'foo x) as (setq foo x) for trivially better code and so + ;; that we get applicable warnings. Compile everything else (including + ;; malformed calls) like a normal 2-arg byte-coded function. + (if (or (not (eq (car-safe (nth 1 form)) 'quote)) + (not (= (length form) 3)) + (not (= (length (nth 1 form)) 2))) + (byte-compile-two-args form) + (byte-compile-setq (list 'setq (nth 1 (nth 1 form)) (nth 2 form))))) + +(defun byte-compile-setq-default (form) + (let ((rest (cdr form))) + ;; emit multiple calls to set-default if necessary + (while rest + (byte-compile-form + (list 'set-default (list 'quote (car rest)) (car (cdr rest))) + (not (null (cdr (cdr rest))))) + (setq rest (cdr (cdr rest)))))) + +(defun byte-compile-set-default (form) + (let ((rest (cdr form))) + (if (cdr (cdr (cdr form))) + ;; emit multiple calls to set-default if necessary; all but last + ;; for-effect (this recurses.) + (while rest + (byte-compile-form + (list 'set-default (car rest) (car (cdr rest))) + (not (null (cdr rest)))) + (setq rest (cdr (cdr rest)))) + ;; else, this is the one-armed version + (let ((var (nth 1 form)) + ;;(val (nth 2 form)) + ) + ;; notice calls to set-default/setq-default for variables which + ;; have not been declared with defvar/defconst. + (if (and (memq 'free-vars byte-compile-warnings) + (or (null var) + (and (eq (car-safe var) 'quote) + (= 2 (length var))))) + (let ((sym (nth 1 var)) + cell) + (or (and sym (symbolp sym) (globally-boundp sym)) + (and (setq cell (assq sym byte-compile-bound-variables)) + (setcdr cell (logior (cdr cell) + byte-compile-assigned-bit))) + (memq sym byte-compile-free-assignments) + (if (or (not (symbolp sym)) (memq sym '(t nil))) + (progn + (byte-compile-warn + "Attempt to set-globally %s %s" + (if (symbolp sym) "constant" "nonvariable") + (prin1-to-string sym))) + (progn + (byte-compile-warn "assignment to free variable %s" sym) + (setq byte-compile-free-assignments + (cons sym byte-compile-free-assignments))))))) + ;; now emit a normal call to set-default (or possibly multiple calls) + (byte-compile-normal-call form))))) + + +(defun byte-compile-quote (form) + (byte-compile-constant (car (cdr form)))) + +(defun byte-compile-quote-form (form) + (byte-compile-constant (byte-compile-top-level (nth 1 form)))) + + +;;; control structures + +(defun byte-compile-body (body &optional for-effect) + (while (cdr body) + (byte-compile-form (car body) t) + (setq body (cdr body))) + (byte-compile-form (car body) for-effect)) + +(proclaim-inline byte-compile-body-do-effect) +(defun byte-compile-body-do-effect (body) + (byte-compile-body body for-effect) + (setq for-effect nil)) + +(proclaim-inline byte-compile-form-do-effect) +(defun byte-compile-form-do-effect (form) + (byte-compile-form form for-effect) + (setq for-effect nil)) + +(byte-defop-compiler-1 inline byte-compile-progn) +(byte-defop-compiler-1 progn) +(byte-defop-compiler-1 prog1) +(byte-defop-compiler-1 prog2) +(byte-defop-compiler-1 if) +(byte-defop-compiler-1 cond) +(byte-defop-compiler-1 and) +(byte-defop-compiler-1 or) +(byte-defop-compiler-1 while) +(byte-defop-compiler-1 funcall) +(byte-defop-compiler-1 apply byte-compile-funarg) +(byte-defop-compiler-1 mapcar byte-compile-funarg) +(byte-defop-compiler-1 mapatoms byte-compile-funarg) +(byte-defop-compiler-1 mapconcat byte-compile-funarg) +(byte-defop-compiler-1 let) +(byte-defop-compiler-1 let*) + +(defun byte-compile-progn (form) + (byte-compile-body-do-effect (cdr form))) + +(defun byte-compile-prog1 (form) + (byte-compile-form-do-effect (car (cdr form))) + (byte-compile-body (cdr (cdr form)) t)) + +(defun byte-compile-prog2 (form) + (byte-compile-form (nth 1 form) t) + (byte-compile-form-do-effect (nth 2 form)) + (byte-compile-body (cdr (cdr (cdr form))) t)) + +(defmacro byte-compile-goto-if (cond discard tag) + (` (byte-compile-goto + (if (, cond) + (if (, discard) 'byte-goto-if-not-nil 'byte-goto-if-not-nil-else-pop) + (if (, discard) 'byte-goto-if-nil 'byte-goto-if-nil-else-pop)) + (, tag)))) + +(defun byte-compile-if (form) + (byte-compile-form (car (cdr form))) + (if (null (nthcdr 3 form)) + ;; No else-forms + (let ((donetag (byte-compile-make-tag))) + (byte-compile-goto-if nil for-effect donetag) + (byte-compile-form (nth 2 form) for-effect) + (byte-compile-out-tag donetag)) + (let ((donetag (byte-compile-make-tag)) (elsetag (byte-compile-make-tag))) + (byte-compile-goto 'byte-goto-if-nil elsetag) + (byte-compile-form (nth 2 form) for-effect) + (byte-compile-goto 'byte-goto donetag) + (byte-compile-out-tag elsetag) + (byte-compile-body (cdr (cdr (cdr form))) for-effect) + (byte-compile-out-tag donetag))) + (setq for-effect nil)) + +(defun byte-compile-cond (clauses) + (let ((donetag (byte-compile-make-tag)) + nexttag clause) + (while (setq clauses (cdr clauses)) + (setq clause (car clauses)) + (cond ((or (eq (car clause) t) + (and (eq (car-safe (car clause)) 'quote) + (car-safe (cdr-safe (car clause))))) + ;; Unconditional clause + (setq clause (cons t clause) + clauses nil)) + ((cdr clauses) + (byte-compile-form (car clause)) + (if (null (cdr clause)) + ;; First clause is a singleton. + (byte-compile-goto-if t for-effect donetag) + (setq nexttag (byte-compile-make-tag)) + (byte-compile-goto 'byte-goto-if-nil nexttag) + (byte-compile-body (cdr clause) for-effect) + (byte-compile-goto 'byte-goto donetag) + (byte-compile-out-tag nexttag))))) + ;; Last clause + (and (cdr clause) (not (eq (car clause) t)) + (progn (byte-compile-form (car clause)) + (byte-compile-goto-if nil for-effect donetag) + (setq clause (cdr clause)))) + (byte-compile-body-do-effect clause) + (byte-compile-out-tag donetag))) + +(defun byte-compile-and (form) + (let ((failtag (byte-compile-make-tag)) + (args (cdr form))) + (if (null args) + (byte-compile-form-do-effect t) + (while (cdr args) + (byte-compile-form (car args)) + (byte-compile-goto-if nil for-effect failtag) + (setq args (cdr args))) + (byte-compile-form-do-effect (car args)) + (byte-compile-out-tag failtag)))) + +(defun byte-compile-or (form) + (let ((wintag (byte-compile-make-tag)) + (args (cdr form))) + (if (null args) + (byte-compile-form-do-effect nil) + (while (cdr args) + (byte-compile-form (car args)) + (byte-compile-goto-if t for-effect wintag) + (setq args (cdr args))) + (byte-compile-form-do-effect (car args)) + (byte-compile-out-tag wintag)))) + +(defun byte-compile-while (form) + (let ((endtag (byte-compile-make-tag)) + (looptag (byte-compile-make-tag))) + (byte-compile-out-tag looptag) + (byte-compile-form (car (cdr form))) + (byte-compile-goto-if nil for-effect endtag) + (byte-compile-body (cdr (cdr form)) t) + (byte-compile-goto 'byte-goto looptag) + (byte-compile-out-tag endtag) + (setq for-effect nil))) + +(defun byte-compile-funcall (form) + (mapcar 'byte-compile-form (cdr form)) + (byte-compile-out 'byte-call (length (cdr (cdr form))))) + + +(defun byte-compile-let (form) + ;; First compute the binding values in the old scope. + (let ((varlist (car (cdr form)))) + (while varlist + (if (consp (car varlist)) + (byte-compile-form (car (cdr (car varlist)))) + (byte-compile-push-constant nil)) + (setq varlist (cdr varlist)))) + (let ((byte-compile-bound-variables + (cons 'new-scope byte-compile-bound-variables)) + (varlist (reverse (car (cdr form)))) + (extra-flags + ;; If this let is of the form (let (...) (byte-code ...)) + ;; then assume that it is the result of a transformation of + ;; ((lambda (...) (byte-code ... )) ...) and thus compile + ;; the variable bindings as if they were arglist bindings + ;; (which matters for what warnings.) + (if (eq 'byte-code (car-safe (nth 2 form))) + byte-compile-arglist-bit + nil))) + (while varlist + (byte-compile-variable-ref 'byte-varbind + (if (consp (car varlist)) + (car (car varlist)) + (car varlist)) + extra-flags) + (setq varlist (cdr varlist))) + (byte-compile-body-do-effect (cdr (cdr form))) + (if (memq 'unused-vars byte-compile-warnings) + ;; done compiling in this scope, warn now. + (byte-compile-warn-about-unused-variables)) + (byte-compile-out 'byte-unbind (length (car (cdr form)))))) + +(defun byte-compile-let* (form) + (let ((byte-compile-bound-variables + (cons 'new-scope byte-compile-bound-variables)) + (varlist (copy-sequence (car (cdr form))))) + (while varlist + (if (atom (car varlist)) + (byte-compile-push-constant nil) + (byte-compile-form (car (cdr (car varlist)))) + (setcar varlist (car (car varlist)))) + (byte-compile-variable-ref 'byte-varbind (car varlist)) + (setq varlist (cdr varlist))) + (byte-compile-body-do-effect (cdr (cdr form))) + (if (memq 'unused-vars byte-compile-warnings) + ;; done compiling in this scope, warn now. + (byte-compile-warn-about-unused-variables)) + (byte-compile-out 'byte-unbind (length (car (cdr form)))))) + + +(byte-defop-compiler-1 /= byte-compile-negated) +(byte-defop-compiler-1 atom byte-compile-negated) +(byte-defop-compiler-1 nlistp byte-compile-negated) + +(put '/= 'byte-compile-negated-op '=) +(put 'atom 'byte-compile-negated-op 'consp) +(put 'nlistp 'byte-compile-negated-op 'listp) + +(defun byte-compile-negated (form) + (byte-compile-form-do-effect (byte-compile-negation-optimizer form))) + +;; Even when optimization is off, /= is optimized to (not (= ...)). +(defun byte-compile-negation-optimizer (form) + ;; an optimizer for forms where is less efficient than (not ) + (list 'not + (cons (or (get (car form) 'byte-compile-negated-op) + (error + "Compiler error: `%s' has no `byte-compile-negated-op' property" + (car form))) + (cdr form)))) + +;;; other tricky macro-like special-forms + +(byte-defop-compiler-1 catch) +(byte-defop-compiler-1 unwind-protect) +(byte-defop-compiler-1 condition-case) +(byte-defop-compiler-1 save-excursion) +(byte-defop-compiler-1 save-current-buffer) +(byte-defop-compiler-1 save-restriction) +(byte-defop-compiler-1 save-window-excursion) +(byte-defop-compiler-1 with-output-to-temp-buffer) +;; no track-mouse. + +(defun byte-compile-catch (form) + (byte-compile-form (car (cdr form))) + (byte-compile-push-constant + (byte-compile-top-level (cons 'progn (cdr (cdr form))) for-effect)) + (byte-compile-out 'byte-catch 0)) + +(defun byte-compile-unwind-protect (form) + (byte-compile-push-constant + (byte-compile-top-level-body (cdr (cdr form)) t)) + (byte-compile-out 'byte-unwind-protect 0) + (byte-compile-form-do-effect (car (cdr form))) + (byte-compile-out 'byte-unbind 1)) + +;;(defun byte-compile-track-mouse (form) +;; (byte-compile-form +;; (list +;; 'funcall +;; (list 'quote +;; (list 'lambda nil +;; (cons 'track-mouse +;; (byte-compile-top-level-body (cdr form)))))))) + +(defun byte-compile-condition-case (form) + (let* ((var (nth 1 form)) + (byte-compile-bound-variables + (if var + (cons (cons var 0) + (cons 'new-scope byte-compile-bound-variables)) + (cons 'new-scope byte-compile-bound-variables)))) + (or (symbolp var) + (byte-compile-warn + "%s is not a variable-name or nil (in condition-case)" + (prin1-to-string var))) + (byte-compile-push-constant var) + (byte-compile-push-constant (byte-compile-top-level + (nth 2 form) for-effect)) + (let ((clauses (cdr (cdr (cdr form)))) + compiled-clauses) + (while clauses + (let* ((clause (car clauses)) + (condition (car clause))) + (cond ((not (or (symbolp condition) + (and (listp condition) + (let ((syms condition) (ok t)) + (while syms + (if (not (symbolp (car syms))) + (setq ok nil)) + (setq syms (cdr syms))) + ok)))) + (byte-compile-warn + "%s is not a symbol naming a condition or a list of such (in condition-case)" + (prin1-to-string condition))) +;; ((not (or (eq condition 't) +;; (and (stringp (get condition 'error-message)) +;; (consp (get condition 'error-conditions))))) +;; (byte-compile-warn +;; "%s is not a known condition name (in condition-case)" +;; condition)) + ) + (setq compiled-clauses + (cons (cons condition + (byte-compile-top-level-body + (cdr clause) for-effect)) + compiled-clauses))) + (setq clauses (cdr clauses))) + (byte-compile-push-constant (nreverse compiled-clauses))) + (if (memq 'unused-vars byte-compile-warnings) + ;; done compiling in this scope, warn now. + (byte-compile-warn-about-unused-variables)) + (byte-compile-out 'byte-condition-case 0))) + + +(defun byte-compile-save-excursion (form) + (byte-compile-out 'byte-save-excursion 0) + (byte-compile-body-do-effect (cdr form)) + (byte-compile-out 'byte-unbind 1)) + +(defun byte-compile-save-restriction (form) + (byte-compile-out 'byte-save-restriction 0) + (byte-compile-body-do-effect (cdr form)) + (byte-compile-out 'byte-unbind 1)) + +(defun byte-compile-save-current-buffer (form) + (if (byte-compile-version-cond byte-compile-emacs19-compatibility) + ;; `save-current-buffer' special form is not available in XEmacs 19. + (byte-compile-form + `(let ((_byte_compiler_save_buffer_emulation_closure_ (current-buffer))) + (unwind-protect + (progn ,@(cdr form)) + (and (buffer-live-p _byte_compiler_save_buffer_emulation_closure_) + (set-buffer _byte_compiler_save_buffer_emulation_closure_))))) + (byte-compile-out 'byte-save-current-buffer 0) + (byte-compile-body-do-effect (cdr form)) + (byte-compile-out 'byte-unbind 1))) + +(defun byte-compile-save-window-excursion (form) + (byte-compile-push-constant + (byte-compile-top-level-body (cdr form) for-effect)) + (byte-compile-out 'byte-save-window-excursion 0)) + +(defun byte-compile-with-output-to-temp-buffer (form) + (byte-compile-form (car (cdr form))) + (byte-compile-out 'byte-temp-output-buffer-setup 0) + (byte-compile-body (cdr (cdr form))) + (byte-compile-out 'byte-temp-output-buffer-show 0)) + + +;;; top-level forms elsewhere + +(byte-defop-compiler-1 defun) +(byte-defop-compiler-1 defmacro) +(byte-defop-compiler-1 defvar) +(byte-defop-compiler-1 defconst byte-compile-defvar) +(byte-defop-compiler-1 autoload) +;; According to Mly this can go now that lambda is a macro +;(byte-defop-compiler-1 lambda byte-compile-lambda-form) +(byte-defop-compiler-1 defalias) +(byte-defop-compiler-1 define-function) + +(defun byte-compile-defun (form) + ;; This is not used for file-level defuns with doc strings. + (byte-compile-two-args ; Use this to avoid byte-compile-fset's warning. + (list 'fset (list 'quote (nth 1 form)) + (byte-compile-byte-code-maker + (byte-compile-lambda (cons 'lambda (cdr (cdr form))))))) + (byte-compile-discard) + (byte-compile-constant (nth 1 form))) + +(defun byte-compile-defmacro (form) + ;; This is not used for file-level defmacros with doc strings. + (byte-compile-body-do-effect + (list (list 'fset (list 'quote (nth 1 form)) + (let ((code (byte-compile-byte-code-maker + (byte-compile-lambda + (cons 'lambda (cdr (cdr form))))))) + (if (eq (car-safe code) 'make-byte-code) + (list 'cons ''macro code) + (list 'quote (cons 'macro (eval code)))))) + (list 'quote (nth 1 form))))) + +(defun byte-compile-defvar (form) + ;; This is not used for file-level defvar/consts with doc strings: + ;; byte-compile-file-form-defvar will be used in that case. + (let ((var (nth 1 form)) + (value (nth 2 form)) + (string (nth 3 form))) + (if (> (length form) 4) + (byte-compile-warn "%s used with too many args" (car form))) + (if (memq 'free-vars byte-compile-warnings) + (setq byte-compile-bound-variables + (cons (cons var byte-compile-global-bit) + byte-compile-bound-variables))) + (byte-compile-body-do-effect + (list (if (cdr (cdr form)) + (if (eq (car form) 'defconst) + (list 'setq var value) + (list 'or (list 'boundp (list 'quote var)) + (list 'setq var value)))) + ;; Put the defined variable in this library's load-history entry + ;; just as a real defvar would. + (list 'setq 'current-load-list + (list 'cons (list 'quote var) + 'current-load-list)) + (if string + (list 'put (list 'quote var) ''variable-documentation string)) + (list 'quote var))))) + +(defun byte-compile-autoload (form) + (and (byte-compile-constp (nth 1 form)) + (byte-compile-constp (nth 5 form)) + (memq (eval (nth 5 form)) '(t macro)) ; macro-p + (not (fboundp (eval (nth 1 form)))) + (byte-compile-warn + "The compiler ignores `autoload' except at top level. You should + probably put the autoload of the macro `%s' at top-level." + (eval (nth 1 form)))) + (byte-compile-normal-call form)) + +;; Lambda's in valid places are handled as special cases by various code. +;; The ones that remain are errors. +;; According to Mly this can go now that lambda is a macro +;(defun byte-compile-lambda-form (form) +; (byte-compile-warn +; "`lambda' used in function position is invalid: probably you mean #'%s" +; (let ((print-escape-newlines t) +; (print-level 4) +; (print-length 4)) +; (prin1-to-string form))) +; (byte-compile-normal-call +; (list 'signal ''error +; (list 'quote (list "`lambda' used in function position" form))))) + +;; Compile normally, but deal with warnings for the function being defined. +(defun byte-compile-defalias (form) + (if (and (consp (cdr form)) (consp (nth 1 form)) + (eq (car (nth 1 form)) 'quote) + (consp (cdr (nth 1 form))) + (symbolp (nth 1 (nth 1 form))) + (consp (nthcdr 2 form)) + (consp (nth 2 form)) + (eq (car (nth 2 form)) 'quote) + (consp (cdr (nth 2 form))) + (symbolp (nth 1 (nth 2 form)))) + (progn + (byte-compile-defalias-warn (nth 1 (nth 1 form)) + (nth 1 (nth 2 form))) + (setq byte-compile-function-environment + (cons (cons (nth 1 (nth 1 form)) + (nth 1 (nth 2 form))) + byte-compile-function-environment)))) + (byte-compile-normal-call form)) + +(defun byte-compile-define-function (form) + (byte-compile-defalias form)) + +;; Turn off warnings about prior calls to the function being defalias'd. +;; This could be smarter and compare those calls with +;; the function it is being aliased to. +(defun byte-compile-defalias-warn (new alias) + (let ((calls (assq new byte-compile-unresolved-functions))) + (if calls + (setq byte-compile-unresolved-functions + (delq calls byte-compile-unresolved-functions))))) + +;;; tags + +;; Note: Most operations will strip off the 'TAG, but it speeds up +;; optimization to have the 'TAG as a part of the tag. +;; Tags will be (TAG . (tag-number . stack-depth)). +(defun byte-compile-make-tag () + (list 'TAG (setq byte-compile-tag-number (1+ byte-compile-tag-number)))) + + +(defun byte-compile-out-tag (tag) + (setq byte-compile-output (cons tag byte-compile-output)) + (if (cdr (cdr tag)) + (progn + ;; ## remove this someday + (and byte-compile-depth + (not (= (cdr (cdr tag)) byte-compile-depth)) + (error "Compiler bug: depth conflict at tag %d" (car (cdr tag)))) + (setq byte-compile-depth (cdr (cdr tag)))) + (setcdr (cdr tag) byte-compile-depth))) + +(defun byte-compile-goto (opcode tag) + (setq byte-compile-output (cons (cons opcode tag) byte-compile-output)) + (setcdr (cdr tag) (if (memq opcode byte-goto-always-pop-ops) + (1- byte-compile-depth) + byte-compile-depth)) + (setq byte-compile-depth (and (not (eq opcode 'byte-goto)) + (1- byte-compile-depth)))) + +(defun byte-compile-out (opcode offset) + (setq byte-compile-output (cons (cons opcode offset) byte-compile-output)) + (cond ((eq opcode 'byte-call) + (setq byte-compile-depth (- byte-compile-depth offset))) + ((eq opcode 'byte-return) + ;; This is actually an unnecessary case, because there should be + ;; no more opcodes behind byte-return. + (setq byte-compile-depth nil)) + (t + (setq byte-compile-depth (+ byte-compile-depth + (or (aref byte-stack+-info + (symbol-value opcode)) + (- (1- offset)))) + byte-compile-maxdepth (max byte-compile-depth + byte-compile-maxdepth)))) + ;;(if (< byte-compile-depth 0) (error "Compiler error: stack underflow")) + ) + + +;;; call tree stuff + +(defun byte-compile-annotate-call-tree (form) + (let (entry) + ;; annotate the current call + (if (setq entry (assq (car form) byte-compile-call-tree)) + (or (memq byte-compile-current-form (nth 1 entry)) ;callers + (setcar (cdr entry) + (cons byte-compile-current-form (nth 1 entry)))) + (setq byte-compile-call-tree + (cons (list (car form) (list byte-compile-current-form) nil) + byte-compile-call-tree))) + ;; annotate the current function + (if (setq entry (assq byte-compile-current-form byte-compile-call-tree)) + (or (memq (car form) (nth 2 entry)) ;called + (setcar (cdr (cdr entry)) + (cons (car form) (nth 2 entry)))) + (setq byte-compile-call-tree + (cons (list byte-compile-current-form nil (list (car form))) + byte-compile-call-tree))) + )) + +;; Renamed from byte-compile-report-call-tree +;; to avoid interfering with completion of byte-compile-file. +;;;###autoload +(defun display-call-tree (&optional filename) + "Display a call graph of a specified file. +This lists which functions have been called, what functions called +them, and what functions they call. The list includes all functions +whose definitions have been compiled in this Emacs session, as well as +all functions called by those functions. + +The call graph does not include macros, inline functions, or +primitives that the byte-code interpreter knows about directly \(eq, +cons, etc.\). + +The call tree also lists those functions which are not known to be called +\(that is, to which no calls have been compiled\), and which cannot be +invoked interactively." + (interactive) + (message "Generating call tree...") + (with-output-to-temp-buffer "*Call-Tree*" + (set-buffer "*Call-Tree*") + (erase-buffer) + (message "Generating call tree... (sorting on %s)" + byte-compile-call-tree-sort) + (insert "Call tree for " + (cond ((null byte-compile-current-file) (or filename "???")) + ((stringp byte-compile-current-file) + byte-compile-current-file) + (t (buffer-name byte-compile-current-file))) + " sorted on " + (prin1-to-string byte-compile-call-tree-sort) + ":\n\n") + (if byte-compile-call-tree-sort + (setq byte-compile-call-tree + (sort byte-compile-call-tree + (cond + ((eq byte-compile-call-tree-sort 'callers) + (function (lambda (x y) (< (length (nth 1 x)) + (length (nth 1 y)))))) + ((eq byte-compile-call-tree-sort 'calls) + (function (lambda (x y) (< (length (nth 2 x)) + (length (nth 2 y)))))) + ((eq byte-compile-call-tree-sort 'calls+callers) + (function (lambda (x y) (< (+ (length (nth 1 x)) + (length (nth 2 x))) + (+ (length (nth 1 y)) + (length (nth 2 y))))))) + ((eq byte-compile-call-tree-sort 'name) + (function (lambda (x y) (string< (car x) + (car y))))) + (t (error + "`byte-compile-call-tree-sort': `%s' - unknown sort mode" + byte-compile-call-tree-sort)))))) + (message "Generating call tree...") + (let ((rest byte-compile-call-tree) + (b (current-buffer)) + f p + callers calls) + (while rest + (prin1 (car (car rest)) b) + (setq callers (nth 1 (car rest)) + calls (nth 2 (car rest))) + (insert "\t" + (cond ((not (fboundp (setq f (car (car rest))))) + (if (null f) + " ";; shouldn't insert nil then, actually -sk + " ")) + ((subrp (setq f (symbol-function f))) + " ") + ((symbolp f) + (format " ==> %s" f)) + ((compiled-function-p f) + "") + ((not (consp f)) + "") + ((eq 'macro (car f)) + (if (or (compiled-function-p (cdr f)) + (assq 'byte-code (cdr (cdr (cdr f))))) + " " + " ")) + ((assq 'byte-code (cdr (cdr f))) + "") + ((eq 'lambda (car f)) + "") + (t "???")) + (format " (%d callers + %d calls = %d)" + ;; Does the optimizer eliminate common subexpressions?-sk + (length callers) + (length calls) + (+ (length callers) (length calls))) + "\n") + (if callers + (progn + (insert " called by:\n") + (setq p (point)) + (insert " " (if (car callers) + (mapconcat 'symbol-name callers ", ") + "")) + (let ((fill-prefix " ")) + (fill-region-as-paragraph p (point))))) + (if calls + (progn + (insert " calls:\n") + (setq p (point)) + (insert " " (mapconcat 'symbol-name calls ", ")) + (let ((fill-prefix " ")) + (fill-region-as-paragraph p (point))))) + (insert "\n") + (setq rest (cdr rest))) + + (message "Generating call tree...(finding uncalled functions...)") + (setq rest byte-compile-call-tree) + (let ((uncalled nil)) + (while rest + (or (nth 1 (car rest)) + (null (setq f (car (car rest)))) + (byte-compile-fdefinition f t) + (commandp (byte-compile-fdefinition f nil)) + (setq uncalled (cons f uncalled))) + (setq rest (cdr rest))) + (if uncalled + (let ((fill-prefix " ")) + (insert "Noninteractive functions not known to be called:\n ") + (setq p (point)) + (insert (mapconcat 'symbol-name (nreverse uncalled) ", ")) + (fill-region-as-paragraph p (point))))) + ) + (message "Generating call tree...done.") + )) + + +;;; by crl@newton.purdue.edu +;;; Only works noninteractively. +;;;###autoload +(defun batch-byte-compile () + "Run `byte-compile-file' on the files remaining on the command line. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. +Each file is processed even if an error occurred previously. +For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\"" + ;; command-line-args-left is what is left of the command line (from + ;; startup.el) + (defvar command-line-args-left) ;Avoid 'free variable' warning + (if (not noninteractive) + (error "`batch-byte-compile' is to be used only with -batch")) + (let ((error nil) + (debug-issue-ebola-notices 0)) ; Hack -slb + (while command-line-args-left + (if (file-directory-p (expand-file-name (car command-line-args-left))) + (let ((files (directory-files (car command-line-args-left))) + source dest) + (while files + (if (and (string-match emacs-lisp-file-regexp (car files)) + (not (auto-save-file-name-p (car files))) + (setq source (expand-file-name + (car files) + (car command-line-args-left))) + (setq dest (byte-compile-dest-file source)) + (file-exists-p dest) + (file-newer-than-file-p source dest)) + (if (null (batch-byte-compile-1 source)) + (setq error t))) + (setq files (cdr files)))) + (if (null (batch-byte-compile-1 (car command-line-args-left))) + (setq error t))) + (setq command-line-args-left (cdr command-line-args-left))) + (message "Done") + (kill-emacs (if error 1 0)))) + +(defun batch-byte-compile-1 (file) + (condition-case err + (progn (byte-compile-file file) t) + (error + (princ ">>Error occurred processing ") + (princ file) + (princ ": ") + (if (fboundp 'display-error) ; XEmacs 19.8+ + (display-error err nil) + (princ (or (get (car err) 'error-message) (car err))) + (mapcar '(lambda (x) (princ " ") (prin1 x)) (cdr err))) + (princ "\n") + nil))) + +;;;###autoload +(defun batch-byte-recompile-directory-norecurse () + "Same as `batch-byte-recompile-directory' but without recursion." + (setq byte-recompile-directory-recursively nil) + (batch-byte-recompile-directory)) + +;;;###autoload +(defun batch-byte-recompile-directory () + "Runs `byte-recompile-directory' on the dirs remaining on the command line. +Must be used only with `-batch', and kills Emacs on completion. +For example, invoke `xemacs -batch -f batch-byte-recompile-directory .'." + ;; command-line-args-left is what is left of the command line (startup.el) + (defvar command-line-args-left) ;Avoid 'free variable' warning + (if (not noninteractive) + (error "batch-byte-recompile-directory is to be used only with -batch")) + (or command-line-args-left + (setq command-line-args-left '("."))) + (let ((byte-recompile-directory-ignore-errors-p t) + (debug-issue-ebola-notices 0)) + (while command-line-args-left + (byte-recompile-directory (car command-line-args-left)) + (setq command-line-args-left (cdr command-line-args-left)))) + (kill-emacs 0)) + +(make-obsolete 'elisp-compile-defun 'compile-defun) +(make-obsolete 'byte-compile-report-call-tree 'display-call-tree) + +;; other make-obsolete calls in obsolete.el. + +(provide 'byte-compile) +(provide 'bytecomp) + + +;;; report metering (see the hacks in bytecode.c) + +(if (boundp 'byte-code-meter) + (defun byte-compile-report-ops () + (defvar byte-code-meter) + (with-output-to-temp-buffer "*Meter*" + (set-buffer "*Meter*") + (let ((i 0) n op off) + (while (< i 256) + (setq n (aref (aref byte-code-meter 0) i) + off nil) + (if t ;(not (zerop n)) + (progn + (setq op i) + (setq off nil) + (cond ((< op byte-nth) + (setq off (logand op 7)) + (setq op (logand op 248))) + ((>= op byte-constant) + (setq off (- op byte-constant) + op byte-constant))) + (setq op (aref byte-code-vector op)) + (insert (format "%-4d" i)) + (insert (symbol-name op)) + (if off (insert " [" (int-to-string off) "]")) + (indent-to 40) + (insert (int-to-string n) "\n"))) + (setq i (1+ i))))))) + + +;; To avoid "lisp nesting exceeds max-lisp-eval-depth" when bytecomp compiles +;; itself, compile some of its most used recursive functions (at load time). +;; +(eval-when-compile + (or (compiled-function-p (symbol-function 'byte-compile-form)) + (assq 'byte-code (symbol-function 'byte-compile-form)) + (let ((byte-optimize nil) ; do it fast + (byte-compile-warnings nil)) + (mapcar '(lambda (x) + (or noninteractive (message "compiling %s..." x)) + (byte-compile x) + (or noninteractive (message "compiling %s...done" x))) + '(byte-compile-normal-call + byte-compile-form + byte-compile-body + ;; Inserted some more than necessary, to speed it up. + byte-compile-top-level + byte-compile-out-toplevel + byte-compile-constant + byte-compile-variable-ref)))) + nil) + +;;; bytecomp.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp/auto-autoloads.el --- a/lisp/bytecomp/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'bytecomp-autoloads) (error "Already loaded")) - -;;;### (autoloads (batch-byte-recompile-directory batch-byte-recompile-directory-norecurse batch-byte-compile display-call-tree byte-compile-sexp byte-compile compile-defun byte-compile-file byte-recompile-file byte-recompile-directory byte-force-recompile) "bytecomp" "bytecomp/bytecomp.el") - -(autoload 'byte-force-recompile "bytecomp" "\ -Recompile every `.el' file in DIRECTORY that already has a `.elc' file. -Files in subdirectories of DIRECTORY are processed also." t nil) - -(autoload 'byte-recompile-directory "bytecomp" "\ -Recompile every `.el' file in DIRECTORY that needs recompilation. -This is if a `.elc' file exists but is older than the `.el' file. -Files in subdirectories of DIRECTORY are processed also unless argument -NORECURSION is non-nil. - -If the `.elc' file does not exist, normally the `.el' file is *not* compiled. -But a prefix argument (optional second arg) means ask user, -for each such `.el' file, whether to compile it. Prefix argument 0 means -don't ask and compile the file anyway. - -A nonzero prefix argument also means ask about each subdirectory. - -If the fourth argument FORCE is non-nil, -recompile every `.el' file that already has a `.elc' file." t nil) - -(autoload 'byte-recompile-file "bytecomp" "\ -Recompile a file of Lisp code named FILENAME if it needs recompilation. -This is if the `.elc' file exists but is older than the `.el' file. - -If the `.elc' file does not exist, normally the `.el' file is *not* -compiled. But a prefix argument (optional second arg) means ask user -whether to compile it. Prefix argument 0 don't ask and recompile anyway." t nil) - -(autoload 'byte-compile-file "bytecomp" "\ -Compile a file of Lisp code named FILENAME into a file of byte code. -The output file's name is made by appending `c' to the end of FILENAME. -With prefix arg (noninteractively: 2nd arg), load the file after compiling." t nil) - -(autoload 'compile-defun "bytecomp" "\ -Compile and evaluate the current top-level form. -Print the result in the minibuffer. -With argument, insert value in current buffer after the form." t nil) - -(autoload 'byte-compile "bytecomp" "\ -If FORM is a symbol, byte-compile its function definition. -If FORM is a lambda or a macro, byte-compile it as a function." nil nil) - -(autoload 'byte-compile-sexp "bytecomp" "\ -Compile and return SEXP." nil nil) - -(autoload 'display-call-tree "bytecomp" "\ -Display a call graph of a specified file. -This lists which functions have been called, what functions called -them, and what functions they call. The list includes all functions -whose definitions have been compiled in this Emacs session, as well as -all functions called by those functions. - -The call graph does not include macros, inline functions, or -primitives that the byte-code interpreter knows about directly (eq, -cons, etc.). - -The call tree also lists those functions which are not known to be called -\(that is, to which no calls have been compiled), and which cannot be -invoked interactively." t nil) - -(autoload 'batch-byte-compile "bytecomp" "\ -Run `byte-compile-file' on the files remaining on the command line. -Use this from the command line, with `-batch'; -it won't work in an interactive Emacs. -Each file is processed even if an error occurred previously. -For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\"" nil nil) - -(autoload 'batch-byte-recompile-directory-norecurse "bytecomp" "\ -Same as `batch-byte-recompile-directory' but without recursion." nil nil) - -(autoload 'batch-byte-recompile-directory "bytecomp" "\ -Runs `byte-recompile-directory' on the dirs remaining on the command line. -Must be used only with `-batch', and kills Emacs on completion. -For example, invoke `xemacs -batch -f batch-byte-recompile-directory .'." nil nil) - -;;;*** - -;;;### (autoloads (disassemble) "disass" "bytecomp/disass.el") - -(autoload 'disassemble "disass" "\ -Print disassembled code for OBJECT in (optional) BUFFER. -OBJECT can be a symbol defined as a function, or a function itself -\(a lambda expression or a compiled-function object). -If OBJECT is not already compiled, we compile it, but do not -redefine OBJECT if it is a symbol." t nil) - -;;;*** - -(provide 'bytecomp-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp/byte-optimize.el --- a/lisp/bytecomp/byte-optimize.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1956 +0,0 @@ -;;; byte-opt.el --- the optimization passes of the emacs-lisp byte compiler. - -;;; Copyright (c) 1991, 1994 Free Software Foundation, Inc. - -;; Author: Jamie Zawinski -;; Hallvard Furuseth -;; Keywords: internal - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;;; ======================================================================== -;;; "No matter how hard you try, you can't make a racehorse out of a pig. -;;; You can, however, make a faster pig." -;;; -;;; Or, to put it another way, the emacs byte compiler is a VW Bug. This code -;;; makes it be a VW Bug with fuel injection and a turbocharger... You're -;;; still not going to make it go faster than 70 mph, but it might be easier -;;; to get it there. -;;; - -;;; TO DO: -;;; -;;; (apply '(lambda (x &rest y) ...) 1 (foo)) -;;; -;;; maintain a list of functions known not to access any global variables -;;; (actually, give them a 'dynamically-safe property) and then -;;; (let ( v1 v2 ... vM vN ) <...dynamically-safe...> ) ==> -;;; (let ( v1 v2 ... vM ) vN <...dynamically-safe...> ) -;;; by recursing on this, we might be able to eliminate the entire let. -;;; However certain variables should never have their bindings optimized -;;; away, because they affect everything. -;;; (put 'debug-on-error 'binding-is-magic t) -;;; (put 'debug-on-abort 'binding-is-magic t) -;;; (put 'debug-on-next-call 'binding-is-magic t) -;;; (put 'mocklisp-arguments 'binding-is-magic t) -;;; (put 'inhibit-quit 'binding-is-magic t) -;;; (put 'quit-flag 'binding-is-magic t) -;;; (put 't 'binding-is-magic t) -;;; (put 'nil 'binding-is-magic t) -;;; possibly also -;;; (put 'gc-cons-threshold 'binding-is-magic t) -;;; (put 'track-mouse 'binding-is-magic t) -;;; others? -;;; -;;; Simple defsubsts often produce forms like -;;; (let ((v1 (f1)) (v2 (f2)) ...) -;;; (FN v1 v2 ...)) -;;; It would be nice if we could optimize this to -;;; (FN (f1) (f2) ...) -;;; but we can't unless FN is dynamically-safe (it might be dynamically -;;; referring to the bindings that the lambda arglist established.) -;;; One of the uncountable lossages introduced by dynamic scope... -;;; -;;; Maybe there should be a control-structure that says "turn on -;;; fast-and-loose type-assumptive optimizations here." Then when -;;; we see a form like (car foo) we can from then on assume that -;;; the variable foo is of type cons, and optimize based on that. -;;; But, this won't win much because of (you guessed it) dynamic -;;; scope. Anything down the stack could change the value. -;;; (Another reason it doesn't work is that it is perfectly valid -;;; to call car with a null argument.) A better approach might -;;; be to allow type-specification of the form -;;; (put 'foo 'arg-types '(float (list integer) dynamic)) -;;; (put 'foo 'result-type 'bool) -;;; It should be possible to have these types checked to a certain -;;; degree. -;;; -;;; collapse common subexpressions -;;; -;;; It would be nice if redundant sequences could be factored out as well, -;;; when they are known to have no side-effects: -;;; (list (+ a b c) (+ a b c)) --> a b add c add dup list-2 -;;; but beware of traps like -;;; (cons (list x y) (list x y)) -;;; -;;; Tail-recursion elimination is not really possible in Emacs Lisp. -;;; Tail-recursion elimination is almost always impossible when all variables -;;; have dynamic scope, but given that the "return" byteop requires the -;;; binding stack to be empty (rather than emptying it itself), there can be -;;; no truly tail-recursive Emacs Lisp functions that take any arguments or -;;; make any bindings. -;;; -;;; Here is an example of an Emacs Lisp function which could safely be -;;; byte-compiled tail-recursively: -;;; -;;; (defun tail-map (fn list) -;;; (cond (list -;;; (funcall fn (car list)) -;;; (tail-map fn (cdr list))))) -;;; -;;; However, if there was even a single let-binding around the COND, -;;; it could not be byte-compiled, because there would be an "unbind" -;;; byte-op between the final "call" and "return." Adding a -;;; Bunbind_all byteop would fix this. -;;; -;;; (defun foo (x y z) ... (foo a b c)) -;;; ... (const foo) (varref a) (varref b) (varref c) (call 3) END: (return) -;;; ... (varref a) (varbind x) (varref b) (varbind y) (varref c) (varbind z) (goto 0) END: (unbind-all) (return) -;;; ... (varref a) (varset x) (varref b) (varset y) (varref c) (varset z) (goto 0) END: (return) -;;; -;;; this also can be considered tail recursion: -;;; -;;; ... (const foo) (varref a) (call 1) (goto X) ... X: (return) -;;; could generalize this by doing the optimization -;;; (goto X) ... X: (return) --> (return) -;;; -;;; But this doesn't solve all of the problems: although by doing tail- -;;; recursion elimination in this way, the call-stack does not grow, the -;;; binding-stack would grow with each recursive step, and would eventually -;;; overflow. I don't believe there is any way around this without lexical -;;; scope. -;;; -;;; Wouldn't it be nice if Emacs Lisp had lexical scope. -;;; -;;; Idea: the form (lexical-scope) in a file means that the file may be -;;; compiled lexically. This proclamation is file-local. Then, within -;;; that file, "let" would establish lexical bindings, and "let-dynamic" -;;; would do things the old way. (Or we could use CL "declare" forms.) -;;; We'd have to notice defvars and defconsts, since those variables should -;;; always be dynamic, and attempting to do a lexical binding of them -;;; should simply do a dynamic binding instead. -;;; But! We need to know about variables that were not necessarily defvarred -;;; in the file being compiled (doing a boundp check isn't good enough.) -;;; Fdefvar() would have to be modified to add something to the plist. -;;; -;;; A major disadvantage of this scheme is that the interpreter and compiler -;;; would have different semantics for files compiled with (dynamic-scope). -;;; Since this would be a file-local optimization, there would be no way to -;;; modify the interpreter to obey this (unless the loader was hacked -;;; in some grody way, but that's a really bad idea.) -;;; -;;; HA! HA! HA! RMS removed the following paragraph from his version of -;;; byte-opt.el, proving once again his stubborn refusal to accept any -;;; developments in computer science that occurred after the late 1970's. -;;; -;;; Really the Right Thing is to make lexical scope the default across -;;; the board, in the interpreter and compiler, and just FIX all of -;;; the code that relies on dynamic scope of non-defvarred variables. - -;; Other things to consider: - -;;;;; Associative math should recognize subcalls to identical function: -;;;(disassemble (lambda (x) (+ (+ (foo) 1) (+ (bar) 2)))) -;;;;; This should generate the same as (1+ x) and (1- x) - -;;;(disassemble (lambda (x) (cons (+ x 1) (- x 1)))) -;;;;; An awful lot of functions always return a non-nil value. If they're -;;;;; error free also they may act as true-constants. - -;;;(disassemble (lambda (x) (and (point) (foo)))) -;;;;; When -;;;;; - all but one arguments to a function are constant -;;;;; - the non-constant argument is an if-expression (cond-expression?) -;;;;; then the outer function can be distributed. If the guarding -;;;;; condition is side-effect-free [assignment-free] then the other -;;;;; arguments may be any expressions. Since, however, the code size -;;;;; can increase this way they should be "simple". Compare: - -;;;(disassemble (lambda (x) (eq (if (point) 'a 'b) 'c))) -;;;(disassemble (lambda (x) (if (point) (eq 'a 'c) (eq 'b 'c)))) - -;;;;; (car (cons A B)) -> (progn B A) -;;;(disassemble (lambda (x) (car (cons (foo) 42)))) - -;;;;; (cdr (cons A B)) -> (progn A B) -;;;(disassemble (lambda (x) (cdr (cons 42 (foo))))) - -;;;;; (car (list A B ...)) -> (progn B ... A) -;;;(disassemble (lambda (x) (car (list (foo) 42 (bar))))) - -;;;;; (cdr (list A B ...)) -> (progn A (list B ...)) -;;;(disassemble (lambda (x) (cdr (list 42 (foo) (bar))))) - - -;;; Code: - -(require 'byte-compile "bytecomp") - -(defun byte-compile-log-lap-1 (format &rest args) - (if (aref byte-code-vector 0) - (error "The old version of the disassembler is loaded. Reload new-bytecomp as well.")) - (byte-compile-log-1 - (apply 'format format - (let (c a) - (mapcar '(lambda (arg) - (if (not (consp arg)) - (if (and (symbolp arg) - (string-match "^byte-" (symbol-name arg))) - (intern (substring (symbol-name arg) 5)) - arg) - (if (integerp (setq c (car arg))) - (error "non-symbolic byte-op %s" c)) - (if (eq c 'TAG) - (setq c arg) - (setq a (cond ((memq c byte-goto-ops) - (car (cdr (cdr arg)))) - ((memq c byte-constref-ops) - (car (cdr arg))) - (t (cdr arg)))) - (setq c (symbol-name c)) - (if (string-match "^byte-." c) - (setq c (intern (substring c 5))))) - (if (eq c 'constant) (setq c 'const)) - (if (and (eq (cdr arg) 0) - (not (memq c '(unbind call const)))) - c - (format "(%s %s)" c a)))) - args))))) - -(defmacro byte-compile-log-lap (format-string &rest args) - (list 'and - '(memq byte-optimize-log '(t byte)) - (cons 'byte-compile-log-lap-1 - (cons format-string args)))) - - -;;; byte-compile optimizers to support inlining - -(put 'inline 'byte-optimizer 'byte-optimize-inline-handler) - -(defun byte-optimize-inline-handler (form) - "byte-optimize-handler for the `inline' special-form." - (cons 'progn - (mapcar - '(lambda (sexp) - (let ((fn (car-safe sexp))) - (if (and (symbolp fn) - (or (cdr (assq fn byte-compile-function-environment)) - (and (fboundp fn) - (not (or (cdr (assq fn byte-compile-macro-environment)) - (and (consp (setq fn (symbol-function fn))) - (eq (car fn) 'macro)) - (subrp fn)))))) - (byte-compile-inline-expand sexp) - sexp))) - (cdr form)))) - - -;; Splice the given lap code into the current instruction stream. -;; If it has any labels in it, you're responsible for making sure there -;; are no collisions, and that byte-compile-tag-number is reasonable -;; after this is spliced in. The provided list is destroyed. -(defun byte-inline-lapcode (lap) - (setq byte-compile-output (nconc (nreverse lap) byte-compile-output))) - - -(defun byte-compile-inline-expand (form) - (let* ((name (car form)) - (fn (or (cdr (assq name byte-compile-function-environment)) - (and (fboundp name) (symbol-function name))))) - (if (null fn) - (progn - (byte-compile-warn "attempt to inline %s before it was defined" name) - form) - ;; else - (if (and (consp fn) (eq (car fn) 'autoload)) - (progn - (load (nth 1 fn)) - (setq fn (or (cdr (assq name byte-compile-function-environment)) - (and (fboundp name) (symbol-function name)))))) - (if (and (consp fn) (eq (car fn) 'autoload)) - (error "file \"%s\" didn't define \"%s\"" (nth 1 fn) name)) - (if (symbolp fn) - (byte-compile-inline-expand (cons fn (cdr form))) - (if (compiled-function-p fn) - (progn - (fetch-bytecode fn) - (cons (list 'lambda (compiled-function-arglist fn) - (list 'byte-code - (compiled-function-instructions fn) - (compiled-function-constants fn) - (compiled-function-stack-depth fn))) - (cdr form))) - (if (not (eq (car fn) 'lambda)) (error "%s is not a lambda" name)) - (cons fn (cdr form))))))) - -;;; ((lambda ...) ...) -;;; -(defun byte-compile-unfold-lambda (form &optional name) - (or name (setq name "anonymous lambda")) - (let ((lambda (car form)) - (values (cdr form))) - (if (compiled-function-p lambda) - (setq lambda (list 'lambda (compiled-function-arglist lambda) - (list 'byte-code - (compiled-function-instructions lambda) - (compiled-function-constants lambda) - (compiled-function-stack-depth lambda))))) - (let ((arglist (nth 1 lambda)) - (body (cdr (cdr lambda))) - optionalp restp - bindings) - (if (and (stringp (car body)) (cdr body)) - (setq body (cdr body))) - (if (and (consp (car body)) (eq 'interactive (car (car body)))) - (setq body (cdr body))) - (while arglist - (cond ((eq (car arglist) '&optional) - ;; ok, I'll let this slide because funcall_lambda() does... - ;; (if optionalp (error "multiple &optional keywords in %s" name)) - (if restp (error "&optional found after &rest in %s" name)) - (if (null (cdr arglist)) - (error "nothing after &optional in %s" name)) - (setq optionalp t)) - ((eq (car arglist) '&rest) - ;; ...but it is by no stretch of the imagination a reasonable - ;; thing that funcall_lambda() allows (&rest x y) and - ;; (&rest x &optional y) in arglists. - (if (null (cdr arglist)) - (error "nothing after &rest in %s" name)) - (if (cdr (cdr arglist)) - (error "multiple vars after &rest in %s" name)) - (setq restp t)) - (restp - (setq bindings (cons (list (car arglist) - (and values (cons 'list values))) - bindings) - values nil)) - ((and (not optionalp) (null values)) - (byte-compile-warn "attempt to open-code %s with too few arguments" name) - (setq arglist nil values 'too-few)) - (t - (setq bindings (cons (list (car arglist) (car values)) - bindings) - values (cdr values)))) - (setq arglist (cdr arglist))) - (if values - (progn - (or (eq values 'too-few) - (byte-compile-warn - "attempt to open-code %s with too many arguments" name)) - form) - (let ((newform - (if bindings - (cons 'let (cons (nreverse bindings) body)) - (cons 'progn body)))) - (byte-compile-log " %s\t==>\t%s" form newform) - newform))))) - - -;;; implementing source-level optimizers - -(defun byte-optimize-form-code-walker (form for-effect) - ;; - ;; For normal function calls, We can just mapcar the optimizer the cdr. But - ;; we need to have special knowledge of the syntax of the special forms - ;; like let and defun (that's why they're special forms :-). (Actually, - ;; the important aspect is that they are subrs that don't evaluate all of - ;; their args.) - ;; - (let ((fn (car-safe form)) - tmp) - (cond ((not (consp form)) - (if (not (and for-effect - (or byte-compile-delete-errors - (not (symbolp form)) - (eq form t)))) - form)) - ((eq fn 'quote) - (if (cdr (cdr form)) - (byte-compile-warn "malformed quote form: %s" - (prin1-to-string form))) - ;; map (quote nil) to nil to simplify optimizer logic. - ;; map quoted constants to nil if for-effect (just because). - (and (nth 1 form) - (not for-effect) - form)) - ((or (compiled-function-p fn) - (eq 'lambda (car-safe fn))) - (byte-compile-unfold-lambda form)) - ((memq fn '(let let*)) - ;; recursively enter the optimizer for the bindings and body - ;; of a let or let*. This for depth-firstness: forms that - ;; are more deeply nested are optimized first. - (cons fn - (cons - (mapcar '(lambda (binding) - (if (symbolp binding) - binding - (if (cdr (cdr binding)) - (byte-compile-warn "malformed let binding: %s" - (prin1-to-string binding))) - (list (car binding) - (byte-optimize-form (nth 1 binding) nil)))) - (nth 1 form)) - (byte-optimize-body (cdr (cdr form)) for-effect)))) - ((eq fn 'cond) - (cons fn - (mapcar '(lambda (clause) - (if (consp clause) - (cons - (byte-optimize-form (car clause) nil) - (byte-optimize-body (cdr clause) for-effect)) - (byte-compile-warn "malformed cond form: %s" - (prin1-to-string clause)) - clause)) - (cdr form)))) - ((eq fn 'progn) - ;; as an extra added bonus, this simplifies (progn ) --> - (if (cdr (cdr form)) - (progn - (setq tmp (byte-optimize-body (cdr form) for-effect)) - (if (cdr tmp) (cons 'progn tmp) (car tmp))) - (byte-optimize-form (nth 1 form) for-effect))) - ((eq fn 'prog1) - (if (cdr (cdr form)) - (cons 'prog1 - (cons (byte-optimize-form (nth 1 form) for-effect) - (byte-optimize-body (cdr (cdr form)) t))) - (byte-optimize-form (nth 1 form) for-effect))) - ((eq fn 'prog2) - (cons 'prog2 - (cons (byte-optimize-form (nth 1 form) t) - (cons (byte-optimize-form (nth 2 form) for-effect) - (byte-optimize-body (cdr (cdr (cdr form))) t))))) - - ((memq fn '(save-excursion save-restriction save-current-buffer)) - ;; those subrs which have an implicit progn; it's not quite good - ;; enough to treat these like normal function calls. - ;; This can turn (save-excursion ...) into (save-excursion) which - ;; will be optimized away in the lap-optimize pass. - (cons fn (byte-optimize-body (cdr form) for-effect))) - - ((eq fn 'with-output-to-temp-buffer) - ;; this is just like the above, except for the first argument. - (cons fn - (cons - (byte-optimize-form (nth 1 form) nil) - (byte-optimize-body (cdr (cdr form)) for-effect)))) - - ((eq fn 'if) - (cons fn - (cons (byte-optimize-form (nth 1 form) nil) - (cons - (byte-optimize-form (nth 2 form) for-effect) - (byte-optimize-body (nthcdr 3 form) for-effect))))) - - ((memq fn '(and or)) ; remember, and/or are control structures. - ;; take forms off the back until we can't any more. - ;; In the future it could conceivably be a problem that the - ;; subexpressions of these forms are optimized in the reverse - ;; order, but it's ok for now. - (if for-effect - (let ((backwards (reverse (cdr form)))) - (while (and backwards - (null (setcar backwards - (byte-optimize-form (car backwards) - for-effect)))) - (setq backwards (cdr backwards))) - (if (and (cdr form) (null backwards)) - (byte-compile-log - " all subforms of %s called for effect; deleted" form)) - (and backwards - (cons fn (nreverse backwards)))) - (cons fn (mapcar 'byte-optimize-form (cdr form))))) - - ((eq fn 'interactive) - (byte-compile-warn "misplaced interactive spec: %s" - (prin1-to-string form)) - nil) - - ((memq fn '(defun defmacro function - condition-case save-window-excursion)) - ;; These forms are compiled as constants or by breaking out - ;; all the subexpressions and compiling them separately. - form) - - ((eq fn 'unwind-protect) - ;; the "protected" part of an unwind-protect is compiled (and thus - ;; optimized) as a top-level form, so don't do it here. But the - ;; non-protected part has the same for-effect status as the - ;; unwind-protect itself. (The protected part is always for effect, - ;; but that isn't handled properly yet.) - (cons fn - (cons (byte-optimize-form (nth 1 form) for-effect) - (cdr (cdr form))))) - - ((eq fn 'catch) - ;; the body of a catch is compiled (and thus optimized) as a - ;; top-level form, so don't do it here. The tag is never - ;; for-effect. The body should have the same for-effect status - ;; as the catch form itself, but that isn't handled properly yet. - (cons fn - (cons (byte-optimize-form (nth 1 form) nil) - (cdr (cdr form))))) - - ;; If optimization is on, this is the only place that macros are - ;; expanded. If optimization is off, then macroexpansion happens - ;; in byte-compile-form. Otherwise, the macros are already expanded - ;; by the time that is reached. - ((not (eq form - (setq form (macroexpand form - byte-compile-macro-environment)))) - (byte-optimize-form form for-effect)) - - ((not (symbolp fn)) - (or (eq 'mocklisp (car-safe fn)) ; ha! - (byte-compile-warn "%s is a malformed function" - (prin1-to-string fn))) - form) - - ((and for-effect (setq tmp (get fn 'side-effect-free)) - (or byte-compile-delete-errors - (eq tmp 'error-free) - (progn - (byte-compile-warn "%s called for effect" - (prin1-to-string form)) - nil))) - (byte-compile-log " %s called for effect; deleted" fn) - ;; appending a nil here might not be necessary, but it can't hurt. - (byte-optimize-form - (cons 'progn (append (cdr form) '(nil))) t)) - - (t - ;; Otherwise, no args can be considered to be for-effect, - ;; even if the called function is for-effect, because we - ;; don't know anything about that function. - (cons fn (mapcar 'byte-optimize-form (cdr form))))))) - - -(defun byte-optimize-form (form &optional for-effect) - "The source-level pass of the optimizer." - ;; - ;; First, optimize all sub-forms of this one. - (setq form (byte-optimize-form-code-walker form for-effect)) - ;; - ;; after optimizing all subforms, optimize this form until it doesn't - ;; optimize any further. This means that some forms will be passed through - ;; the optimizer many times, but that's necessary to make the for-effect - ;; processing do as much as possible. - ;; - (let (opt new) - (if (and (consp form) - (symbolp (car form)) - (or (and for-effect - ;; we don't have any of these yet, but we might. - (setq opt (get (car form) 'byte-for-effect-optimizer))) - (setq opt (get (car form) 'byte-optimizer))) - (not (eq form (setq new (funcall opt form))))) - (progn -;; (if (equal form new) (error "bogus optimizer -- %s" opt)) - (byte-compile-log " %s\t==>\t%s" form new) - (setq new (byte-optimize-form new for-effect)) - new) - form))) - - -(defun byte-optimize-body (forms all-for-effect) - ;; optimize the cdr of a progn or implicit progn; all forms is a list of - ;; forms, all but the last of which are optimized with the assumption that - ;; they are being called for effect. the last is for-effect as well if - ;; all-for-effect is true. returns a new list of forms. - (let ((rest forms) - (result nil) - fe new) - (while rest - (setq fe (or all-for-effect (cdr rest))) - (setq new (and (car rest) (byte-optimize-form (car rest) fe))) - (if (or new (not fe)) - (setq result (cons new result))) - (setq rest (cdr rest))) - (nreverse result))) - - -;;; some source-level optimizers -;;; -;;; when writing optimizers, be VERY careful that the optimizer returns -;;; something not EQ to its argument if and ONLY if it has made a change. -;;; This implies that you cannot simply destructively modify the list; -;;; you must return something not EQ to it if you make an optimization. -;;; -;;; It is now safe to optimize code such that it introduces new bindings. - -;; I'd like this to be a defsubst, but let's not be self-referential... -(defmacro byte-compile-trueconstp (form) - ;; Returns non-nil if FORM is a non-nil constant. - (` (cond ((consp (, form)) (eq (car (, form)) 'quote)) - ((not (symbolp (, form)))) - ((eq (, form) t))))) - -;; If the function is being called with constant numeric args, -;; evaluate as much as possible at compile-time. This optimizer -;; assumes that the function is associative, like + or *. -(defun byte-optimize-associative-math (form) - (let ((args nil) - (constants nil) - (rest (cdr form))) - (while rest - (if (numberp (car rest)) - (setq constants (cons (car rest) constants)) - (setq args (cons (car rest) args))) - (setq rest (cdr rest))) - (if (cdr constants) - (if args - (list (car form) - (apply (car form) constants) - (if (cdr args) - (cons (car form) (nreverse args)) - (car args))) - (apply (car form) constants)) - form))) - -;; If the function is being called with constant numeric args, -;; evaluate as much as possible at compile-time. This optimizer -;; assumes that the function satisfies -;; (op x1 x2 ... xn) == (op ...(op (op x1 x2) x3) ...xn) -;; like - and /. -(defun byte-optimize-nonassociative-math (form) - (if (or (not (numberp (car (cdr form)))) - (not (numberp (car (cdr (cdr form)))))) - form - (let ((constant (car (cdr form))) - (rest (cdr (cdr form)))) - (while (numberp (car rest)) - (setq constant (funcall (car form) constant (car rest)) - rest (cdr rest))) - (if rest - (cons (car form) (cons constant rest)) - constant)))) - -;;(defun byte-optimize-associative-two-args-math (form) -;; (setq form (byte-optimize-associative-math form)) -;; (if (consp form) -;; (byte-optimize-two-args-left form) -;; form)) - -;;(defun byte-optimize-nonassociative-two-args-math (form) -;; (setq form (byte-optimize-nonassociative-math form)) -;; (if (consp form) -;; (byte-optimize-two-args-right form) -;; form)) - -;; jwz: (byte-optimize-approx-equal 0.0 0.0) was returning nil -;; in xemacs 19.15 because it used < instead of <=. -(defun byte-optimize-approx-equal (x y) - (<= (* (abs (- x y)) 100) (abs (+ x y)))) - -;; Collect all the constants from FORM, after the STARTth arg, -;; and apply FUN to them to make one argument at the end. -;; For functions that can handle floats, that optimization -;; can be incorrect because reordering can cause an overflow -;; that would otherwise be avoided by encountering an arg that is a float. -;; We avoid this problem by (1) not moving float constants and -;; (2) not moving anything if it would cause an overflow. -(defun byte-optimize-delay-constants-math (form start fun) - ;; Merge all FORM's constants from number START, call FUN on them - ;; and put the result at the end. - (let ((rest (nthcdr (1- start) form)) - (orig form) - ;; t means we must check for overflow. - (overflow (memq fun '(+ *)))) - (while (cdr (setq rest (cdr rest))) - (if (integerp (car rest)) - (let (constants) - (setq form (copy-sequence form) - rest (nthcdr (1- start) form)) - (while (setq rest (cdr rest)) - (cond ((integerp (car rest)) - (setq constants (cons (car rest) constants)) - (setcar rest nil)))) - ;; If necessary, check now for overflow - ;; that might be caused by reordering. - (if (and overflow - ;; We have overflow if the result of doing the arithmetic - ;; on floats is not even close to the result - ;; of doing it on integers. - (not (byte-optimize-approx-equal - (apply fun (mapcar 'float constants)) - (float (apply fun constants))))) - (setq form orig) - (setq form (nconc (delq nil form) - (list (apply fun (nreverse constants))))))))) - form)) - -(defun byte-optimize-plus (form) - (setq form (byte-optimize-delay-constants-math form 1 '+)) - (if (memq 0 form) (setq form (delq 0 (copy-sequence form)))) - ;;(setq form (byte-optimize-associative-two-args-math form)) - (cond ((null (cdr form)) - (condition-case () - (eval form) - (error form))) - - ;; `add1' and `sub1' are a marginally fewer instructions - ;; than `plus' and `minus', so use them when possible. - ((and (null (nthcdr 3 form)) - (eq (nth 2 form) 1)) - (list '1+ (nth 1 form))) ; (+ x 1) --> (1+ x) - ((and (null (nthcdr 3 form)) - (eq (nth 1 form) 1)) - (list '1+ (nth 2 form))) ; (+ 1 x) --> (1+ x) - ((and (null (nthcdr 3 form)) - (eq (nth 2 form) -1)) - (list '1- (nth 1 form))) ; (+ x -1) --> (1- x) - ((and (null (nthcdr 3 form)) - (eq (nth 1 form) -1)) - (list '1- (nth 2 form))) ; (+ -1 x) --> (1- x) - -;;; It is not safe to delete the function entirely -;;; (actually, it would be safe if we know the sole arg -;;; is not a marker). -;; ((null (cdr (cdr form))) (nth 1 form)) - (t form))) - -(defun byte-optimize-minus (form) - ;; Put constants at the end, except the last constant. - (setq form (byte-optimize-delay-constants-math form 2 '+)) - ;; Now only first and last element can be a number. - (let ((last (car (reverse (nthcdr 3 form))))) - (cond ((eq 0 last) - ;; (- x y ... 0) --> (- x y ...) - (setq form (copy-sequence form)) - (setcdr (cdr (cdr form)) (delq 0 (nthcdr 3 form)))) - ;; If form is (- CONST foo... CONST), merge first and last. - ((and (numberp (nth 1 form)) - (numberp last)) - (setq form (nconc (list '- (- (nth 1 form) last) (nth 2 form)) - (delq last (copy-sequence (nthcdr 3 form)))))))) - (setq form -;;; It is not safe to delete the function entirely -;;; (actually, it would be safe if we know the sole arg -;;; is not a marker). -;;; (if (eq (nth 2 form) 0) -;;; (nth 1 form) ; (- x 0) --> x - (byte-optimize-predicate - (if (and (null (cdr (cdr (cdr form)))) - (eq (nth 1 form) 0)) ; (- 0 x) --> (- x) - (cons (car form) (cdr (cdr form))) - form)) -;;; ) - ) - - ;; `add1' and `sub1' are a marginally fewer instructions than `plus' - ;; and `minus', so use them when possible. - (cond ((and (null (nthcdr 3 form)) - (eq (nth 2 form) 1)) - (list '1- (nth 1 form))) ; (- x 1) --> (1- x) - ((and (null (nthcdr 3 form)) - (eq (nth 2 form) -1)) - (list '1+ (nth 1 form))) ; (- x -1) --> (1+ x) - (t - form)) - ) - -(defun byte-optimize-multiply (form) - (setq form (byte-optimize-delay-constants-math form 1 '*)) - ;; If there is a constant in FORM, it is now the last element. - (cond ((null (cdr form)) 1) -;;; It is not safe to delete the function entirely -;;; (actually, it would be safe if we know the sole arg -;;; is not a marker or if it appears in other arithmetic). -;;; ((null (cdr (cdr form))) (nth 1 form)) - ((let ((last (car (reverse form)))) - (cond ((eq 0 last) (cons 'progn (cdr form))) - ((eq 1 last) (delq 1 (copy-sequence form))) - ((eq -1 last) (list '- (delq -1 (copy-sequence form)))) - ((and (eq 2 last) - (memq t (mapcar 'symbolp (cdr form)))) - (prog1 (setq form (delq 2 (copy-sequence form))) - (while (not (symbolp (car (setq form (cdr form)))))) - (setcar form (list '+ (car form) (car form))))) - (form)))))) - -(defsubst byte-compile-butlast (form) - (nreverse (cdr (reverse form)))) - -(defun byte-optimize-divide (form) - (setq form (byte-optimize-delay-constants-math form 2 '*)) - (let ((last (car (reverse (cdr (cdr form)))))) - (if (numberp last) - (cond ((= (length form) 3) - (if (and (numberp (nth 1 form)) - (not (zerop last)) - (condition-case nil - (/ (nth 1 form) last) - (error nil))) - (setq form (list 'progn (/ (nth 1 form) last))))) - ((= last 1) - (setq form (byte-compile-butlast form))) - ((numberp (nth 1 form)) - (setq form (cons (car form) - (cons (/ (nth 1 form) last) - (byte-compile-butlast (cdr (cdr form))))) - last nil)))) - (cond -;;; ((null (cdr (cdr form))) -;;; (nth 1 form)) - ((eq (nth 1 form) 0) - (append '(progn) (cdr (cdr form)) '(0))) - ((eq last -1) - (list '- (if (nthcdr 3 form) - (byte-compile-butlast form) - (nth 1 form)))) - (form)))) - -(defun byte-optimize-logmumble (form) - (setq form (byte-optimize-delay-constants-math form 1 (car form))) - (byte-optimize-predicate - (cond ((memq 0 form) - (setq form (if (eq (car form) 'logand) - (cons 'progn (cdr form)) - (delq 0 (copy-sequence form))))) - ((and (eq (car-safe form) 'logior) - (memq -1 form)) - (cons 'progn (cdr form))) - (form)))) - - -(defun byte-optimize-binary-predicate (form) - (if (byte-compile-constp (nth 1 form)) - (if (byte-compile-constp (nth 2 form)) - (condition-case () - (list 'quote (eval form)) - (error form)) - ;; This can enable some lapcode optimizations. - (list (car form) (nth 2 form) (nth 1 form))) - form)) - -(defun byte-optimize-predicate (form) - (let ((ok t) - (rest (cdr form))) - (while (and rest ok) - (setq ok (byte-compile-constp (car rest)) - rest (cdr rest))) - (if ok - (condition-case () - (list 'quote (eval form)) - (error form)) - form))) - -(defun byte-optimize-identity (form) - (if (and (cdr form) (null (cdr (cdr form)))) - (nth 1 form) - (byte-compile-warn "identity called with %d arg%s, but requires 1" - (length (cdr form)) - (if (= 1 (length (cdr form))) "" "s")) - form)) - -(put 'identity 'byte-optimizer 'byte-optimize-identity) - -(put '+ 'byte-optimizer 'byte-optimize-plus) -(put '* 'byte-optimizer 'byte-optimize-multiply) -(put '- 'byte-optimizer 'byte-optimize-minus) -(put '/ 'byte-optimizer 'byte-optimize-divide) -(put 'max 'byte-optimizer 'byte-optimize-associative-math) -(put 'min 'byte-optimizer 'byte-optimize-associative-math) - -(put '= 'byte-optimizer 'byte-optimize-binary-predicate) -(put 'eq 'byte-optimizer 'byte-optimize-binary-predicate) -(put 'eql 'byte-optimizer 'byte-optimize-binary-predicate) -(put 'equal 'byte-optimizer 'byte-optimize-binary-predicate) -(put 'string= 'byte-optimizer 'byte-optimize-binary-predicate) -(put 'string-equal 'byte-optimizer 'byte-optimize-binary-predicate) - -(put '< 'byte-optimizer 'byte-optimize-predicate) -(put '> 'byte-optimizer 'byte-optimize-predicate) -(put '<= 'byte-optimizer 'byte-optimize-predicate) -(put '>= 'byte-optimizer 'byte-optimize-predicate) -(put '1+ 'byte-optimizer 'byte-optimize-predicate) -(put '1- 'byte-optimizer 'byte-optimize-predicate) -(put 'not 'byte-optimizer 'byte-optimize-predicate) -(put 'null 'byte-optimizer 'byte-optimize-predicate) -(put 'memq 'byte-optimizer 'byte-optimize-predicate) -(put 'consp 'byte-optimizer 'byte-optimize-predicate) -(put 'listp 'byte-optimizer 'byte-optimize-predicate) -(put 'symbolp 'byte-optimizer 'byte-optimize-predicate) -(put 'stringp 'byte-optimizer 'byte-optimize-predicate) -(put 'string< 'byte-optimizer 'byte-optimize-predicate) -(put 'string-lessp 'byte-optimizer 'byte-optimize-predicate) - -(put 'logand 'byte-optimizer 'byte-optimize-logmumble) -(put 'logior 'byte-optimizer 'byte-optimize-logmumble) -(put 'logxor 'byte-optimizer 'byte-optimize-logmumble) -(put 'lognot 'byte-optimizer 'byte-optimize-predicate) - -(put 'car 'byte-optimizer 'byte-optimize-predicate) -(put 'cdr 'byte-optimizer 'byte-optimize-predicate) -(put 'car-safe 'byte-optimizer 'byte-optimize-predicate) -(put 'cdr-safe 'byte-optimizer 'byte-optimize-predicate) - - -;; I'm not convinced that this is necessary. Doesn't the optimizer loop -;; take care of this? - Jamie -;; I think this may some times be necessary to reduce ie (quote 5) to 5, -;; so arithmetic optimizers recognize the numeric constant. - Hallvard -(put 'quote 'byte-optimizer 'byte-optimize-quote) -(defun byte-optimize-quote (form) - (if (or (consp (nth 1 form)) - (and (symbolp (nth 1 form)) - ;; XEmacs addition: - (not (keywordp (nth 1 form))) - (not (memq (nth 1 form) '(nil t))))) - form - (nth 1 form))) - -(defun byte-optimize-zerop (form) - (cond ((numberp (nth 1 form)) - (eval form)) - (byte-compile-delete-errors - (list '= (nth 1 form) 0)) - (form))) - -(put 'zerop 'byte-optimizer 'byte-optimize-zerop) - -(defun byte-optimize-and (form) - ;; Simplify if less than 2 args. - ;; if there is a literal nil in the args to `and', throw it and following - ;; forms away, and surround the `and' with (progn ... nil). - (cond ((null (cdr form))) - ((memq nil form) - (list 'progn - (byte-optimize-and - (prog1 (setq form (copy-sequence form)) - (while (nth 1 form) - (setq form (cdr form))) - (setcdr form nil))) - nil)) - ((null (cdr (cdr form))) - (nth 1 form)) - ((byte-optimize-predicate form)))) - -(defun byte-optimize-or (form) - ;; Throw away nil's, and simplify if less than 2 args. - ;; If there is a literal non-nil constant in the args to `or', throw away all - ;; following forms. - (if (memq nil form) - (setq form (delq nil (copy-sequence form)))) - (let ((rest form)) - (while (cdr (setq rest (cdr rest))) - (if (byte-compile-trueconstp (car rest)) - (setq form (copy-sequence form) - rest (setcdr (memq (car rest) form) nil)))) - (if (cdr (cdr form)) - (byte-optimize-predicate form) - (nth 1 form)))) - -(defun byte-optimize-cond (form) - ;; if any clauses have a literal nil as their test, throw them away. - ;; if any clause has a literal non-nil constant as its test, throw - ;; away all following clauses. - (let (rest) - ;; This must be first, to reduce (cond (t ...) (nil)) to (progn t ...) - (while (setq rest (assq nil (cdr form))) - (setq form (delq rest (copy-sequence form)))) - (if (memq nil (cdr form)) - (setq form (delq nil (copy-sequence form)))) - (setq rest form) - (while (setq rest (cdr rest)) - (cond ((byte-compile-trueconstp (car-safe (car rest))) - (cond ((eq rest (cdr form)) - (setq form - (if (cdr (car rest)) - (if (cdr (cdr (car rest))) - (cons 'progn (cdr (car rest))) - (nth 1 (car rest))) - (car (car rest))))) - ((cdr rest) - (setq form (copy-sequence form)) - (setcdr (memq (car rest) form) nil))) - (setq rest nil))))) - ;; - ;; Turn (cond (( )) ... ) into (or (cond ... )) - (if (eq 'cond (car-safe form)) - (let ((clauses (cdr form))) - (if (and (consp (car clauses)) - (null (cdr (car clauses)))) - (list 'or (car (car clauses)) - (byte-optimize-cond - (cons (car form) (cdr (cdr form))))) - form)) - form)) - -(defun byte-optimize-if (form) - ;; (if ) ==> - ;; (if ) ==> (progn ) - ;; (if nil ) ==> (if (not ) (progn )) - ;; (if nil) ==> (if ) - (let ((clause (nth 1 form))) - (cond ((byte-compile-trueconstp clause) - (nth 2 form)) - ((null clause) - (if (nthcdr 4 form) - (cons 'progn (nthcdr 3 form)) - (nth 3 form))) - ((nth 2 form) - (if (equal '(nil) (nthcdr 3 form)) - (list 'if clause (nth 2 form)) - form)) - ((or (nth 3 form) (nthcdr 4 form)) - (list 'if - ;; Don't make a double negative; - ;; instead, take away the one that is there. - (if (and (consp clause) (memq (car clause) '(not null)) - (= (length clause) 2)) ; (not xxxx) or (not (xxxx)) - (nth 1 clause) - (list 'not clause)) - (if (nthcdr 4 form) - (cons 'progn (nthcdr 3 form)) - (nth 3 form)))) - (t - (list 'progn clause nil))))) - -(defun byte-optimize-while (form) - (if (nth 1 form) - form)) - -(put 'and 'byte-optimizer 'byte-optimize-and) -(put 'or 'byte-optimizer 'byte-optimize-or) -(put 'cond 'byte-optimizer 'byte-optimize-cond) -(put 'if 'byte-optimizer 'byte-optimize-if) -(put 'while 'byte-optimizer 'byte-optimize-while) - -;; byte-compile-negation-optimizer lives in bytecomp.el -(put '/= 'byte-optimizer 'byte-compile-negation-optimizer) -(put 'atom 'byte-optimizer 'byte-compile-negation-optimizer) -(put 'nlistp 'byte-optimizer 'byte-compile-negation-optimizer) - - -(defun byte-optimize-funcall (form) - ;; (funcall '(lambda ...) ...) ==> ((lambda ...) ...) - ;; (funcall 'foo ...) ==> (foo ...) - (let ((fn (nth 1 form))) - (if (memq (car-safe fn) '(quote function)) - (cons (nth 1 fn) (cdr (cdr form))) - form))) - -(defun byte-optimize-apply (form) - ;; If the last arg is a literal constant, turn this into a funcall. - ;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...). - (let ((fn (nth 1 form)) - (last (nth (1- (length form)) form))) ; I think this really is fastest - (or (if (or (null last) - (eq (car-safe last) 'quote)) - (if (listp (nth 1 last)) - (let ((butlast (nreverse (cdr (reverse (cdr (cdr form))))))) - (nconc (list 'funcall fn) butlast - (mapcar '(lambda (x) (list 'quote x)) (nth 1 last)))) - (byte-compile-warn - "last arg to apply can't be a literal atom: %s" - (prin1-to-string last)) - nil)) - form))) - -(put 'funcall 'byte-optimizer 'byte-optimize-funcall) -(put 'apply 'byte-optimizer 'byte-optimize-apply) - - -(put 'let 'byte-optimizer 'byte-optimize-letX) -(put 'let* 'byte-optimizer 'byte-optimize-letX) -(defun byte-optimize-letX (form) - (cond ((null (nth 1 form)) - ;; No bindings - (cons 'progn (cdr (cdr form)))) - ((or (nth 2 form) (nthcdr 3 form)) - form) - ;; The body is nil - ((eq (car form) 'let) - (append '(progn) (mapcar 'car-safe (mapcar 'cdr-safe (nth 1 form))) - '(nil))) - (t - (let ((binds (reverse (nth 1 form)))) - (list 'let* (reverse (cdr binds)) (nth 1 (car binds)) nil))))) - - -(put 'nth 'byte-optimizer 'byte-optimize-nth) -(defun byte-optimize-nth (form) - (if (and (= (safe-length form) 3) (memq (nth 1 form) '(0 1))) - (list 'car (if (zerop (nth 1 form)) - (nth 2 form) - (list 'cdr (nth 2 form)))) - (byte-optimize-predicate form))) - -(put 'nthcdr 'byte-optimizer 'byte-optimize-nthcdr) -(defun byte-optimize-nthcdr (form) - (if (and (= (safe-length form) 3) (not (memq (nth 1 form) '(0 1 2)))) - (byte-optimize-predicate form) - (let ((count (nth 1 form))) - (setq form (nth 2 form)) - (while (>= (setq count (1- count)) 0) - (setq form (list 'cdr form))) - form))) - -;;; enumerating those functions which need not be called if the returned -;;; value is not used. That is, something like -;;; (progn (list (something-with-side-effects) (yow)) -;;; (foo)) -;;; may safely be turned into -;;; (progn (progn (something-with-side-effects) (yow)) -;;; (foo)) -;;; Further optimizations will turn (progn (list 1 2 3) 'foo) into 'foo. - -;;; I wonder if I missed any :-\) -(let ((side-effect-free-fns - '(% * + - / /= 1+ 1- < <= = > >= abs acos append aref ash asin atan - assoc assq - boundp buffer-file-name buffer-local-variables buffer-modified-p - buffer-substring - capitalize car-less-than-car car cdr ceiling concat - ;; coordinates-in-window-p not in XEmacs - copy-marker cos count-lines - default-boundp default-value documentation downcase - elt exp expt fboundp featurep - file-directory-p file-exists-p file-locked-p file-name-absolute-p - file-newer-than-file-p file-readable-p file-symlink-p file-writable-p - float floor format - get get-buffer get-buffer-window getenv get-file-buffer - int-to-string - length log log10 logand logb logior lognot logxor lsh - marker-buffer max member memq min mod - next-window nth nthcdr number-to-string - parse-colon-path previous-window - radians-to-degrees rassq regexp-quote reverse round - sin sqrt string< string= string-equal string-lessp string-to-char - string-to-int string-to-number substring symbol-plist - tan upcase user-variable-p vconcat - ;; XEmacs change: window-edges -> window-pixel-edges - window-buffer window-dedicated-p window-pixel-edges window-height - window-hscroll window-minibuffer-p window-width - zerop)) - (side-effect-and-error-free-fns - '(arrayp atom - bobp bolp buffer-end buffer-list buffer-size buffer-string bufferp - car-safe case-table-p cdr-safe char-or-string-p char-table-p - characterp commandp cons - consolep console-live-p consp - current-buffer - ;; XEmacs: extent functions, frame-live-p, various other stuff - devicep device-live-p - dot dot-marker eobp eolp eq eql equal eventp extentp - extent-live-p floatp framep frame-live-p - get-largest-window get-lru-window - identity ignore integerp integer-or-marker-p interactive-p - invocation-directory invocation-name - ;; keymapp may autoload in XEmacs, so not on this list! - list listp - make-marker mark mark-marker markerp memory-limit minibuffer-window - ;; mouse-movement-p not in XEmacs - natnump nlistp not null number-or-marker-p numberp - one-window-p ;; overlayp not in XEmacs - point point-marker point-min point-max processp - range-table-p - selected-window sequencep stringp subrp symbolp syntax-table-p - user-full-name user-login-name user-original-login-name - user-real-login-name user-real-uid user-uid - vector vectorp - window-configuration-p window-live-p windowp))) - (while side-effect-free-fns - (put (car side-effect-free-fns) 'side-effect-free t) - (setq side-effect-free-fns (cdr side-effect-free-fns))) - (while side-effect-and-error-free-fns - (put (car side-effect-and-error-free-fns) 'side-effect-free 'error-free) - (setq side-effect-and-error-free-fns (cdr side-effect-and-error-free-fns))) - nil) - - -(defun byte-compile-splice-in-already-compiled-code (form) - ;; form is (byte-code "..." [...] n) - (if (not (memq byte-optimize '(t lap))) - (byte-compile-normal-call form) - (byte-inline-lapcode - (byte-decompile-bytecode-1 (nth 1 form) (nth 2 form) t)) - (setq byte-compile-maxdepth (max (+ byte-compile-depth (nth 3 form)) - byte-compile-maxdepth)) - (setq byte-compile-depth (1+ byte-compile-depth)))) - -(put 'byte-code 'byte-compile 'byte-compile-splice-in-already-compiled-code) - - -(defconst byte-constref-ops - '(byte-constant byte-constant2 byte-varref byte-varset byte-varbind)) - -;;; This function extracts the bitfields from variable-length opcodes. -;;; Originally defined in disass.el (which no longer uses it.) - -(defun disassemble-offset () - "Don't call this!" - ;; fetch and return the offset for the current opcode. - ;; return NIL if this opcode has no offset - ;; OP, PTR and BYTES are used and set dynamically - (defvar op) - (defvar ptr) - (defvar bytes) - (cond ((< op byte-nth) - (let ((tem (logand op 7))) - (setq op (logand op 248)) - (cond ((eq tem 6) - (setq ptr (1+ ptr)) ;offset in next byte - ;; char-to-int to avoid downstream problems - ;; caused by chars appearing where ints are - ;; expected. In bytecode the bytes in the - ;; opcode string are always interpreted as ints. - (char-to-int (aref bytes ptr))) - ((eq tem 7) - (setq ptr (1+ ptr)) ;offset in next 2 bytes - (+ (aref bytes ptr) - (progn (setq ptr (1+ ptr)) - (lsh (aref bytes ptr) 8)))) - (t tem)))) ;offset was in opcode - ((>= op byte-constant) - (prog1 (- op byte-constant) ;offset in opcode - (setq op byte-constant))) - ((and (>= op byte-constant2) - (<= op byte-goto-if-not-nil-else-pop)) - (setq ptr (1+ ptr)) ;offset in next 2 bytes - (+ (aref bytes ptr) - (progn (setq ptr (1+ ptr)) - (lsh (aref bytes ptr) 8)))) - ;; XEmacs: this code was here before. FSF's first comparison - ;; is (>= op byte-listN). It appears that the rel-goto stuff - ;; does not exist in FSF 19.30. It doesn't exist in 19.28 - ;; either, so I'm going to assume that this is an improvement - ;; on our part and leave it in. --ben - ((and (>= op byte-rel-goto) - (<= op byte-insertN)) - (setq ptr (1+ ptr)) ;offset in next byte - ;; Use char-to-int to avoid downstream problems caused by - ;; chars appearing where ints are expected. In bytecode - ;; the bytes in the opcode string are always interpreted as - ;; ints. - (char-to-int (aref bytes ptr))))) - - -;;; This de-compiler is used for inline expansion of compiled functions, -;;; and by the disassembler. -;;; -;;; This list contains numbers, which are pc values, -;;; before each instruction. -(defun byte-decompile-bytecode (bytes constvec) - "Turns BYTECODE into lapcode, referring to CONSTVEC." - (let ((byte-compile-constants nil) - (byte-compile-variables nil) - (byte-compile-tag-number 0)) - (byte-decompile-bytecode-1 bytes constvec))) - -;; As byte-decompile-bytecode, but updates -;; byte-compile-{constants, variables, tag-number}. -;; If MAKE-SPLICEABLE is true, then `return' opcodes are replaced -;; with `goto's destined for the end of the code. -;; That is for use by the compiler. -;; If MAKE-SPLICEABLE is nil, we are being called for the disassembler. -;; In that case, we put a pc value into the list -;; before each insn (or its label). -(defun byte-decompile-bytecode-1 (bytes constvec &optional make-spliceable) - (let ((length (length bytes)) - (ptr 0) optr tags op offset - ;; tag unused - lap tmp - endtag - ;; (retcount 0) unused - ) - (while (not (= ptr length)) - (or make-spliceable - (setq lap (cons ptr lap))) - (setq op (aref bytes ptr) - optr ptr - offset (disassemble-offset)) ; this does dynamic-scope magic - (setq op (aref byte-code-vector op)) - ;; XEmacs: the next line in FSF 19.30 reads - ;; (cond ((memq op byte-goto-ops) - ;; see the comment above about byte-rel-goto in XEmacs. - (cond ((or (memq op byte-goto-ops) - (cond ((memq op byte-rel-goto-ops) - (setq op (aref byte-code-vector - (- (symbol-value op) - (- byte-rel-goto byte-goto)))) - (setq offset (+ ptr (- offset 127))) - t))) - ;; it's a pc - (setq offset - (cdr (or (assq offset tags) - (car (setq tags - (cons (cons offset - (byte-compile-make-tag)) - tags))))))) - ((cond ((eq op 'byte-constant2) (setq op 'byte-constant) t) - ((memq op byte-constref-ops))) - (setq tmp (aref constvec offset) - offset (if (eq op 'byte-constant) - (byte-compile-get-constant tmp) - (or (assq tmp byte-compile-variables) - (car (setq byte-compile-variables - (cons (list tmp) - byte-compile-variables))))))) - ((and make-spliceable - (eq op 'byte-return)) - (if (= ptr (1- length)) - (setq op nil) - (setq offset (or endtag (setq endtag (byte-compile-make-tag))) - op 'byte-goto)))) - ;; lap = ( [ (pc . (op . arg)) ]* ) - (setq lap (cons (cons optr (cons op (or offset 0))) - lap)) - (setq ptr (1+ ptr))) - ;; take off the dummy nil op that we replaced a trailing "return" with. - (let ((rest lap)) - (while rest - (cond ((numberp (car rest))) - ((setq tmp (assq (car (car rest)) tags)) - ;; this addr is jumped to - (setcdr rest (cons (cons nil (cdr tmp)) - (cdr rest))) - (setq tags (delq tmp tags)) - (setq rest (cdr rest)))) - (setq rest (cdr rest)))) - (if tags (error "optimizer error: missed tags %s" tags)) - (if (null (car (cdr (car lap)))) - (setq lap (cdr lap))) - (if endtag - (setq lap (cons (cons nil endtag) lap))) - ;; remove addrs, lap = ( [ (op . arg) | (TAG tagno) ]* ) - (mapcar (function (lambda (elt) - (if (numberp elt) - elt - (cdr elt)))) - (nreverse lap)))) - - -;;; peephole optimizer - -(defconst byte-tagref-ops (cons 'TAG byte-goto-ops)) - -(defconst byte-conditional-ops - '(byte-goto-if-nil byte-goto-if-not-nil byte-goto-if-nil-else-pop - byte-goto-if-not-nil-else-pop)) - -(defconst byte-after-unbind-ops - '(byte-constant byte-dup - byte-symbolp byte-consp byte-stringp byte-listp byte-numberp byte-integerp - byte-eq byte-equal byte-not - byte-cons byte-list1 byte-list2 ; byte-list3 byte-list4 - byte-interactive-p) - ;; How about other side-effect-free-ops? Is it safe to move an - ;; error invocation (such as from nth) out of an unwind-protect? - "Byte-codes that can be moved past an unbind.") - -(defconst byte-compile-side-effect-and-error-free-ops - '(byte-constant byte-dup byte-symbolp byte-consp byte-stringp byte-listp - byte-integerp byte-numberp byte-eq byte-equal byte-not byte-car-safe - byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max - byte-point-min byte-following-char byte-preceding-char - byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp - byte-current-buffer byte-interactive-p)) - -(defconst byte-compile-side-effect-free-ops - (nconc - '(byte-varref byte-nth byte-memq byte-car byte-cdr byte-length byte-aref - byte-symbol-value byte-get byte-concat2 byte-concat3 byte-sub1 byte-add1 - byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate - byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax - byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt - byte-member byte-assq byte-quo byte-rem) - byte-compile-side-effect-and-error-free-ops)) - -;;; This piece of shit is because of the way DEFVAR_BOOL() variables work. -;;; Consider the code -;;; -;;; (defun foo (flag) -;;; (let ((old-pop-ups pop-up-windows) -;;; (pop-up-windows flag)) -;;; (cond ((not (eq pop-up-windows old-pop-ups)) -;;; (setq old-pop-ups pop-up-windows) -;;; ...)))) -;;; -;;; Uncompiled, old-pop-ups will always be set to nil or t, even if FLAG is -;;; something else. But if we optimize -;;; -;;; varref flag -;;; varbind pop-up-windows -;;; varref pop-up-windows -;;; not -;;; to -;;; varref flag -;;; dup -;;; varbind pop-up-windows -;;; not -;;; -;;; we break the program, because it will appear that pop-up-windows and -;;; old-pop-ups are not EQ when really they are. So we have to know what -;;; the BOOL variables are, and not perform this optimization on them. -;;; -(defconst byte-boolean-vars - '(abbrev-all-caps purify-flag find-file-compare-truenames - find-file-use-truenames find-file-visit-truename - find-file-existing-other-name byte-metering-on - zmacs-regions zmacs-region-active-p zmacs-region-stays - atomic-extent-goto-char-p suppress-early-error-handler - noninteractive ignore-kernel debug-on-quit debug-on-next-call - modifier-keys-are-sticky x-allow-sendevents vms-stmlf-recfm - disable-auto-save-when-buffer-shrinks indent-tabs-mode - load-in-progress load-warn-when-source-newer load-warn-when-source-only - load-ignore-elc-files load-force-doc-strings - fail-on-bucky-bit-character-escapes popup-menu-titles - menubar-show-keybindings completion-ignore-case - canna-empty-info canna-through-info canna-underline - canna-inhibit-hankakukana x-handle-non-fully-specified-fonts - print-escape-newlines print-readably print-gensym - delete-exited-processes truncate-partial-width-windows - visible-bell no-redraw-on-reenter cursor-in-echo-area - inhibit-warning-display parse-sexp-ignore-comments words-include-escapes - scroll-on-clipped-lines pop-up-frames pop-up-windows) - "DEFVAR_BOOL variables. Giving these any non-nil value sets them to t. -If this does not enumerate all DEFVAR_BOOL variables, the byte-optimizer -may generate incorrect code.") - -(defun byte-optimize-lapcode (lap &optional for-effect) - "Simple peephole optimizer. LAP is both modified and returned." - (let (lap0 ;; off0 unused - lap1 ;; off1 - lap2 ;; off2 - (keep-going 'first-time) - (add-depth 0) - rest tmp tmp2 tmp3 - (side-effect-free (if byte-compile-delete-errors - byte-compile-side-effect-free-ops - byte-compile-side-effect-and-error-free-ops))) - (while keep-going - (or (eq keep-going 'first-time) - (byte-compile-log-lap " ---- next pass")) - (setq rest lap - keep-going nil) - (while rest - (setq lap0 (car rest) - lap1 (nth 1 rest) - lap2 (nth 2 rest)) - - ;; You may notice that sequences like "dup varset discard" are - ;; optimized but sequences like "dup varset TAG1: discard" are not. - ;; You may be tempted to change this; resist that temptation. - (cond ;; - ;; pop --> - ;; ...including: - ;; const-X pop --> - ;; varref-X pop --> - ;; dup pop --> - ;; - ((and (eq 'byte-discard (car lap1)) - (memq (car lap0) side-effect-free)) - (setq keep-going t) - (setq tmp (aref byte-stack+-info (symbol-value (car lap0)))) - (setq rest (cdr rest)) - (cond ((= tmp 1) - (byte-compile-log-lap - " %s discard\t-->\t" lap0) - (setq lap (delq lap0 (delq lap1 lap)))) - ((= tmp 0) - (byte-compile-log-lap - " %s discard\t-->\t discard" lap0) - (setq lap (delq lap0 lap))) - ((= tmp -1) - (byte-compile-log-lap - " %s discard\t-->\tdiscard discard" lap0) - (setcar lap0 'byte-discard) - (setcdr lap0 0)) - ((error "Optimizer error: too much on the stack")))) - ;; - ;; goto*-X X: --> X: - ;; - ((and (memq (car lap0) byte-goto-ops) - (eq (cdr lap0) lap1)) - (cond ((eq (car lap0) 'byte-goto) - (setq lap (delq lap0 lap)) - (setq tmp "")) - ((memq (car lap0) byte-goto-always-pop-ops) - (setcar lap0 (setq tmp 'byte-discard)) - (setcdr lap0 0)) - ((error "Depth conflict at tag %d" (nth 2 lap0)))) - (and (memq byte-optimize-log '(t byte)) - (byte-compile-log " (goto %s) %s:\t-->\t%s %s:" - (nth 1 lap1) (nth 1 lap1) - tmp (nth 1 lap1))) - (setq keep-going t)) - ;; - ;; varset-X varref-X --> dup varset-X - ;; varbind-X varref-X --> dup varbind-X - ;; const/dup varset-X varref-X --> const/dup varset-X const/dup - ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup - ;; The latter two can enable other optimizations. - ;; - ((and (eq 'byte-varref (car lap2)) - (eq (cdr lap1) (cdr lap2)) - (memq (car lap1) '(byte-varset byte-varbind))) - (if (and (setq tmp (memq (car (cdr lap2)) byte-boolean-vars)) - (not (eq (car lap0) 'byte-constant))) - nil - (setq keep-going t) - (if (memq (car lap0) '(byte-constant byte-dup)) - (progn - (setq tmp (if (or (not tmp) - (memq (car (cdr lap0)) '(nil t))) - (cdr lap0) - (byte-compile-get-constant t))) - (byte-compile-log-lap " %s %s %s\t-->\t%s %s %s" - lap0 lap1 lap2 lap0 lap1 - (cons (car lap0) tmp)) - (setcar lap2 (car lap0)) - (setcdr lap2 tmp)) - (byte-compile-log-lap " %s %s\t-->\tdup %s" lap1 lap2 lap1) - (setcar lap2 (car lap1)) - (setcar lap1 'byte-dup) - (setcdr lap1 0) - ;; The stack depth gets locally increased, so we will - ;; increase maxdepth in case depth = maxdepth here. - ;; This can cause the third argument to byte-code to - ;; be larger than necessary. - (setq add-depth 1)))) - ;; - ;; dup varset-X discard --> varset-X - ;; dup varbind-X discard --> varbind-X - ;; (the varbind variant can emerge from other optimizations) - ;; - ((and (eq 'byte-dup (car lap0)) - (eq 'byte-discard (car lap2)) - (memq (car lap1) '(byte-varset byte-varbind))) - (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1) - (setq keep-going t - rest (cdr rest)) - (setq lap (delq lap0 (delq lap2 lap)))) - ;; - ;; not goto-X-if-nil --> goto-X-if-non-nil - ;; not goto-X-if-non-nil --> goto-X-if-nil - ;; - ;; it is wrong to do the same thing for the -else-pop variants. - ;; - ((and (eq 'byte-not (car lap0)) - (or (eq 'byte-goto-if-nil (car lap1)) - (eq 'byte-goto-if-not-nil (car lap1)))) - (byte-compile-log-lap " not %s\t-->\t%s" - lap1 - (cons - (if (eq (car lap1) 'byte-goto-if-nil) - 'byte-goto-if-not-nil - 'byte-goto-if-nil) - (cdr lap1))) - (setcar lap1 (if (eq (car lap1) 'byte-goto-if-nil) - 'byte-goto-if-not-nil - 'byte-goto-if-nil)) - (setq lap (delq lap0 lap)) - (setq keep-going t)) - ;; - ;; goto-X-if-nil goto-Y X: --> goto-Y-if-non-nil X: - ;; goto-X-if-non-nil goto-Y X: --> goto-Y-if-nil X: - ;; - ;; it is wrong to do the same thing for the -else-pop variants. - ;; - ((and (or (eq 'byte-goto-if-nil (car lap0)) - (eq 'byte-goto-if-not-nil (car lap0))) ; gotoX - (eq 'byte-goto (car lap1)) ; gotoY - (eq (cdr lap0) lap2)) ; TAG X - (let ((inverse (if (eq 'byte-goto-if-nil (car lap0)) - 'byte-goto-if-not-nil 'byte-goto-if-nil))) - (byte-compile-log-lap " %s %s %s:\t-->\t%s %s:" - lap0 lap1 lap2 - (cons inverse (cdr lap1)) lap2) - (setq lap (delq lap0 lap)) - (setcar lap1 inverse) - (setq keep-going t))) - ;; - ;; const goto-if-* --> whatever - ;; - ((and (eq 'byte-constant (car lap0)) - (memq (car lap1) byte-conditional-ops)) - (cond ((if (or (eq (car lap1) 'byte-goto-if-nil) - (eq (car lap1) 'byte-goto-if-nil-else-pop)) - (car (cdr lap0)) - (not (car (cdr lap0)))) - (byte-compile-log-lap " %s %s\t-->\t" - lap0 lap1) - (setq rest (cdr rest) - lap (delq lap0 (delq lap1 lap)))) - (t - (if (memq (car lap1) byte-goto-always-pop-ops) - (progn - (byte-compile-log-lap " %s %s\t-->\t%s" - lap0 lap1 (cons 'byte-goto (cdr lap1))) - (setq lap (delq lap0 lap))) - (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 - (cons 'byte-goto (cdr lap1)))) - (setcar lap1 'byte-goto))) - (setq keep-going t)) - ;; - ;; varref-X varref-X --> varref-X dup - ;; varref-X [dup ...] varref-X --> varref-X [dup ...] dup - ;; We don't optimize the const-X variations on this here, - ;; because that would inhibit some goto optimizations; we - ;; optimize the const-X case after all other optimizations. - ;; - ((and (eq 'byte-varref (car lap0)) - (progn - (setq tmp (cdr rest)) - (while (eq (car (car tmp)) 'byte-dup) - (setq tmp (cdr tmp))) - t) - (eq (cdr lap0) (cdr (car tmp))) - (eq 'byte-varref (car (car tmp)))) - (if (memq byte-optimize-log '(t byte)) - (let ((str "")) - (setq tmp2 (cdr rest)) - (while (not (eq tmp tmp2)) - (setq tmp2 (cdr tmp2) - str (concat str " dup"))) - (byte-compile-log-lap " %s%s %s\t-->\t%s%s dup" - lap0 str lap0 lap0 str))) - (setq keep-going t) - (setcar (car tmp) 'byte-dup) - (setcdr (car tmp) 0) - (setq rest tmp)) - ;; - ;; TAG1: TAG2: --> TAG1: - ;; (and other references to TAG2 are replaced with TAG1) - ;; - ((and (eq (car lap0) 'TAG) - (eq (car lap1) 'TAG)) - (and (memq byte-optimize-log '(t byte)) - (byte-compile-log " adjacent tags %d and %d merged" - (nth 1 lap1) (nth 1 lap0))) - (setq tmp3 lap) - (while (setq tmp2 (rassq lap0 tmp3)) - (setcdr tmp2 lap1) - (setq tmp3 (cdr (memq tmp2 tmp3)))) - (setq lap (delq lap0 lap) - keep-going t)) - ;; - ;; unused-TAG: --> - ;; - ((and (eq 'TAG (car lap0)) - (not (rassq lap0 lap))) - (and (memq byte-optimize-log '(t byte)) - (byte-compile-log " unused tag %d removed" (nth 1 lap0))) - (setq lap (delq lap0 lap) - keep-going t)) - ;; - ;; goto ... --> goto - ;; return ... --> return - ;; - ((and (memq (car lap0) '(byte-goto byte-return)) - (not (memq (car lap1) '(TAG nil)))) - (setq tmp rest) - (let ((i 0) - (opt-p (memq byte-optimize-log '(t lap))) - str deleted) - (while (and (setq tmp (cdr tmp)) - (not (eq 'TAG (car (car tmp))))) - (if opt-p (setq deleted (cons (car tmp) deleted) - str (concat str " %s") - i (1+ i)))) - (if opt-p - (let ((tagstr - (if (eq 'TAG (car (car tmp))) - (format "%d:" (car (cdr (car tmp)))) - (or (car tmp) "")))) - (if (< i 6) - (apply 'byte-compile-log-lap-1 - (concat " %s" str - " %s\t-->\t%s %s") - lap0 - (nconc (nreverse deleted) - (list tagstr lap0 tagstr))) - (byte-compile-log-lap - " %s <%d unreachable op%s> %s\t-->\t%s %s" - lap0 i (if (= i 1) "" "s") - tagstr lap0 tagstr)))) - (rplacd rest tmp)) - (setq keep-going t)) - ;; - ;; unbind --> unbind - ;; (this may enable other optimizations.) - ;; - ((and (eq 'byte-unbind (car lap1)) - (memq (car lap0) byte-after-unbind-ops)) - (byte-compile-log-lap " %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0) - (setcar rest lap1) - (setcar (cdr rest) lap0) - (setq keep-going t)) - ;; - ;; varbind-X unbind-N --> discard unbind-(N-1) - ;; save-excursion unbind-N --> unbind-(N-1) - ;; save-restriction unbind-N --> unbind-(N-1) - ;; - ((and (eq 'byte-unbind (car lap1)) - (memq (car lap0) '(byte-varbind byte-save-excursion - byte-save-restriction)) - (< 0 (cdr lap1))) - (if (zerop (setcdr lap1 (1- (cdr lap1)))) - (delq lap1 rest)) - (if (eq (car lap0) 'byte-varbind) - (setcar rest (cons 'byte-discard 0)) - (setq lap (delq lap0 lap))) - (byte-compile-log-lap " %s %s\t-->\t%s %s" - lap0 (cons (car lap1) (1+ (cdr lap1))) - (if (eq (car lap0) 'byte-varbind) - (car rest) - (car (cdr rest))) - (if (and (/= 0 (cdr lap1)) - (eq (car lap0) 'byte-varbind)) - (car (cdr rest)) - "")) - (setq keep-going t)) - ;; - ;; goto*-X ... X: goto-Y --> goto*-Y - ;; goto-X ... X: return --> return - ;; - ((and (memq (car lap0) byte-goto-ops) - (memq (car (setq tmp (nth 1 (memq (cdr lap0) lap)))) - '(byte-goto byte-return))) - (cond ((and (not (eq tmp lap0)) - (or (eq (car lap0) 'byte-goto) - (eq (car tmp) 'byte-goto))) - (byte-compile-log-lap " %s [%s]\t-->\t%s" - (car lap0) tmp tmp) - (if (eq (car tmp) 'byte-return) - (setcar lap0 'byte-return)) - (setcdr lap0 (cdr tmp)) - (setq keep-going t)))) - ;; - ;; goto-*-else-pop X ... X: goto-if-* --> whatever - ;; goto-*-else-pop X ... X: discard --> whatever - ;; - ((and (memq (car lap0) '(byte-goto-if-nil-else-pop - byte-goto-if-not-nil-else-pop)) - (memq (car (car (setq tmp (cdr (memq (cdr lap0) lap))))) - (eval-when-compile - (cons 'byte-discard byte-conditional-ops))) - (not (eq lap0 (car tmp)))) - (setq tmp2 (car tmp)) - (setq tmp3 (assq (car lap0) '((byte-goto-if-nil-else-pop - byte-goto-if-nil) - (byte-goto-if-not-nil-else-pop - byte-goto-if-not-nil)))) - (if (memq (car tmp2) tmp3) - (progn (setcar lap0 (car tmp2)) - (setcdr lap0 (cdr tmp2)) - (byte-compile-log-lap " %s-else-pop [%s]\t-->\t%s" - (car lap0) tmp2 lap0)) - ;; Get rid of the -else-pop's and jump one step further. - (or (eq 'TAG (car (nth 1 tmp))) - (setcdr tmp (cons (byte-compile-make-tag) - (cdr tmp)))) - (byte-compile-log-lap " %s [%s]\t-->\t%s " - (car lap0) tmp2 (nth 1 tmp3)) - (setcar lap0 (nth 1 tmp3)) - (setcdr lap0 (nth 1 tmp))) - (setq keep-going t)) - ;; - ;; const goto-X ... X: goto-if-* --> whatever - ;; const goto-X ... X: discard --> whatever - ;; - ((and (eq (car lap0) 'byte-constant) - (eq (car lap1) 'byte-goto) - (memq (car (car (setq tmp (cdr (memq (cdr lap1) lap))))) - (eval-when-compile - (cons 'byte-discard byte-conditional-ops))) - (not (eq lap1 (car tmp)))) - (setq tmp2 (car tmp)) - (cond ((memq (car tmp2) - (if (null (car (cdr lap0))) - '(byte-goto-if-nil byte-goto-if-nil-else-pop) - '(byte-goto-if-not-nil - byte-goto-if-not-nil-else-pop))) - (byte-compile-log-lap " %s goto [%s]\t-->\t%s %s" - lap0 tmp2 lap0 tmp2) - (setcar lap1 (car tmp2)) - (setcdr lap1 (cdr tmp2)) - ;; Let next step fix the (const,goto-if*) sequence. - (setq rest (cons nil rest))) - (t - ;; Jump one step further - (byte-compile-log-lap - " %s goto [%s]\t-->\t goto " - lap0 tmp2) - (or (eq 'TAG (car (nth 1 tmp))) - (setcdr tmp (cons (byte-compile-make-tag) - (cdr tmp)))) - (setcdr lap1 (car (cdr tmp))) - (setq lap (delq lap0 lap)))) - (setq keep-going t)) - ;; - ;; X: varref-Y ... varset-Y goto-X --> - ;; X: varref-Y Z: ... dup varset-Y goto-Z - ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.) - ;; (This is so usual for while loops that it is worth handling). - ;; - ((and (eq (car lap1) 'byte-varset) - (eq (car lap2) 'byte-goto) - (not (memq (cdr lap2) rest)) ;Backwards jump - (eq (car (car (setq tmp (cdr (memq (cdr lap2) lap))))) - 'byte-varref) - (eq (cdr (car tmp)) (cdr lap1)) - (not (memq (car (cdr lap1)) byte-boolean-vars))) - ;;(byte-compile-log-lap " Pulled %s to end of loop" (car tmp)) - (let ((newtag (byte-compile-make-tag))) - (byte-compile-log-lap - " %s: %s ... %s %s\t-->\t%s: %s %s: ... %s %s %s" - (nth 1 (cdr lap2)) (car tmp) - lap1 lap2 - (nth 1 (cdr lap2)) (car tmp) - (nth 1 newtag) 'byte-dup lap1 - (cons 'byte-goto newtag) - ) - (setcdr rest (cons (cons 'byte-dup 0) (cdr rest))) - (setcdr tmp (cons (setcdr lap2 newtag) (cdr tmp)))) - (setq add-depth 1) - (setq keep-going t)) - ;; - ;; goto-X Y: ... X: goto-if*-Y --> goto-if-not-*-X+1 Y: - ;; (This can pull the loop test to the end of the loop) - ;; - ((and (eq (car lap0) 'byte-goto) - (eq (car lap1) 'TAG) - (eq lap1 - (cdr (car (setq tmp (cdr (memq (cdr lap0) lap)))))) - (memq (car (car tmp)) - '(byte-goto byte-goto-if-nil byte-goto-if-not-nil - byte-goto-if-nil-else-pop))) -;; (byte-compile-log-lap " %s %s, %s %s --> moved conditional" -;; lap0 lap1 (cdr lap0) (car tmp)) - (let ((newtag (byte-compile-make-tag))) - (byte-compile-log-lap - "%s %s: ... %s: %s\t-->\t%s ... %s:" - lap0 (nth 1 lap1) (nth 1 (cdr lap0)) (car tmp) - (cons (cdr (assq (car (car tmp)) - '((byte-goto-if-nil . byte-goto-if-not-nil) - (byte-goto-if-not-nil . byte-goto-if-nil) - (byte-goto-if-nil-else-pop . - byte-goto-if-not-nil-else-pop) - (byte-goto-if-not-nil-else-pop . - byte-goto-if-nil-else-pop)))) - newtag) - - (nth 1 newtag) - ) - (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp))) - (if (eq (car (car tmp)) 'byte-goto-if-nil-else-pop) - ;; We can handle this case but not the -if-not-nil case, - ;; because we won't know which non-nil constant to push. - (setcdr rest (cons (cons 'byte-constant - (byte-compile-get-constant nil)) - (cdr rest)))) - (setcar lap0 (nth 1 (memq (car (car tmp)) - '(byte-goto-if-nil-else-pop - byte-goto-if-not-nil - byte-goto-if-nil - byte-goto-if-not-nil - byte-goto byte-goto)))) - ) - (setq keep-going t)) - ) - (setq rest (cdr rest))) - ) - ;; Cleanup stage: - ;; Rebuild byte-compile-constants / byte-compile-variables. - ;; Simple optimizations that would inhibit other optimizations if they - ;; were done in the optimizing loop, and optimizations which there is no - ;; need to do more than once. - (setq byte-compile-constants nil - byte-compile-variables nil) - (setq rest lap) - (while rest - (setq lap0 (car rest) - lap1 (nth 1 rest)) - (if (memq (car lap0) byte-constref-ops) - (if (eq (cdr lap0) 'byte-constant) - (or (memq (cdr lap0) byte-compile-variables) - (setq byte-compile-variables (cons (cdr lap0) - byte-compile-variables))) - (or (memq (cdr lap0) byte-compile-constants) - (setq byte-compile-constants (cons (cdr lap0) - byte-compile-constants))))) - (cond (;; - ;; const-C varset-X const-C --> const-C dup varset-X - ;; const-C varbind-X const-C --> const-C dup varbind-X - ;; - (and (eq (car lap0) 'byte-constant) - (eq (car (nth 2 rest)) 'byte-constant) - (eq (cdr lap0) (car (nth 2 rest))) - (memq (car lap1) '(byte-varbind byte-varset))) - (byte-compile-log-lap " %s %s %s\t-->\t%s dup %s" - lap0 lap1 lap0 lap0 lap1) - (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1))) - (setcar (cdr rest) (cons 'byte-dup 0)) - (setq add-depth 1)) - ;; - ;; const-X [dup/const-X ...] --> const-X [dup ...] dup - ;; varref-X [dup/varref-X ...] --> varref-X [dup ...] dup - ;; - ((memq (car lap0) '(byte-constant byte-varref)) - (setq tmp rest - tmp2 nil) - (while (progn - (while (eq 'byte-dup (car (car (setq tmp (cdr tmp)))))) - (and (eq (cdr lap0) (cdr (car tmp))) - (eq (car lap0) (car (car tmp))))) - (setcar tmp (cons 'byte-dup 0)) - (setq tmp2 t)) - (if tmp2 - (byte-compile-log-lap - " %s [dup/%s]...\t-->\t%s dup..." lap0 lap0 lap0))) - ;; - ;; unbind-N unbind-M --> unbind-(N+M) - ;; - ((and (eq 'byte-unbind (car lap0)) - (eq 'byte-unbind (car lap1))) - (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 - (cons 'byte-unbind - (+ (cdr lap0) (cdr lap1)))) - (setq keep-going t) - (setq lap (delq lap0 lap)) - (setcdr lap1 (+ (cdr lap1) (cdr lap0)))) - ) - (setq rest (cdr rest))) - (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) - lap) - -(provide 'byte-optimize) - - -;; To avoid "lisp nesting exceeds max-lisp-eval-depth" when this file compiles -;; itself, compile some of its most used recursive functions (at load time). -;; -(eval-when-compile - (or (compiled-function-p (symbol-function 'byte-optimize-form)) - (assq 'byte-code (symbol-function 'byte-optimize-form)) - (let ((byte-optimize nil) - (byte-compile-warnings nil)) - (mapcar '(lambda (x) - (or noninteractive (message "compiling %s..." x)) - (byte-compile x) - (or noninteractive (message "compiling %s...done" x))) - '(byte-optimize-form - byte-optimize-body - byte-optimize-predicate - byte-optimize-binary-predicate - ;; Inserted some more than necessary, to speed it up. - byte-optimize-form-code-walker - byte-optimize-lapcode)))) - nil) - -;;; byte-optimize.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp/bytecomp-runtime.el --- a/lisp/bytecomp/bytecomp-runtime.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -;;; byte-run.el --- byte-compiler support for inlining - -;; Copyright (C) 1992 Free Software Foundation, Inc. - -;; Author: Jamie Zawinski -;; Hallvard Furuseth -;; Keywords: internal - -;; The code in this file should always be loaded, because it defines things -;; like "defsubst" which should work interpreted as well. The code in -;; bytecomp.el and byte-optimize.el can be loaded as needed. -;; -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;;; interface to selectively inlining functions. -;;; This only happens when source-code optimization is turned on. - -;;; Code: - -;; Redefined in byte-optimize.el. -;; This is not documented--it's not clear that we should promote it. -(fset 'inline 'progn) -(put 'inline 'lisp-indent-hook 0) - - -;;; Interface to inline functions. - -;; FSF comments the next two out, but I see no reason to do so. --ben -(defmacro proclaim-inline (&rest fns) - "Cause the named functions to be open-coded when called from compiled code. -They will only be compiled open-coded when byte-optimize is true." - (cons 'eval-and-compile - (apply - 'nconc - (mapcar - '(lambda (x) - (` ((or (memq (get '(, x) 'byte-optimizer) - '(nil byte-compile-inline-expand)) - (error - "%s already has a byte-optimizer, can't make it inline" - '(, x))) - (put '(, x) 'byte-optimizer 'byte-compile-inline-expand)))) - fns)))) - - -(defmacro proclaim-notinline (&rest fns) - "Cause the named functions to no longer be open-coded." - (cons 'eval-and-compile - (apply - 'nconc - (mapcar - '(lambda (x) - (` ((if (eq (get '(, x) 'byte-optimizer) - 'byte-compile-inline-expand) - (put '(, x) 'byte-optimizer nil))))) - fns)))) - -;; This has a special byte-hunk-handler in bytecomp.el. -(defmacro defsubst (name arglist &rest body) - "Define an inline function. The syntax is just like that of `defun'." - (or (memq (get name 'byte-optimizer) - '(nil byte-compile-inline-expand)) - (error "`%s' is a primitive" name)) - (list 'prog1 - (cons 'defun (cons name (cons arglist body))) - (list 'proclaim-inline name))) -; Instead of the above line, FSF has this: -; (list 'eval-and-compile -; (list 'put (list 'quote name) -; ''byte-optimizer ''byte-compile-inline-expand)))) - -(defun make-obsolete (fn new) - "Make the byte-compiler warn that FUNCTION is obsolete. -The warning will say that NEW should be used instead. -If NEW is a string, that is the `use instead' message." - (interactive "aMake function obsolete: \nxObsoletion replacement: ") - (let ((handler (get fn 'byte-compile))) - (if (eq 'byte-compile-obsolete handler) - (setcar (get fn 'byte-obsolete-info) new) - (put fn 'byte-obsolete-info (cons new handler)) - (put fn 'byte-compile 'byte-compile-obsolete))) - fn) - -(defun make-obsolete-variable (var new) - "Make the byte-compiler warn that VARIABLE is obsolete, -and NEW should be used instead. If NEW is a string, then that is the -`use instead' message." - (interactive - (list - (let ((str (completing-read "Make variable obsolete: " obarray 'boundp t))) - (if (equal str "") (error "")) - (intern str)) - (car (read-from-string (read-string "Obsoletion replacement: "))))) - (put var 'byte-obsolete-variable new) - var) - -;; By overwhelming demand, we separate out truly obsolete symbols from -;; those that are present for GNU Emacs compatibility. -(defun make-compatible (fn new) - "Make the byte-compiler know that FUNCTION is provided for compatibility. -The warning will say that NEW should be used instead. -If NEW is a string, that is the `use instead' message." - (interactive "aMake function compatible: \nxCompatible replacement: ") - (let ((handler (get fn 'byte-compile))) - (if (eq 'byte-compile-compatible handler) - (setcar (get fn 'byte-compatible-info) new) - (put fn 'byte-compatible-info (cons new handler)) - (put fn 'byte-compile 'byte-compile-compatible))) - fn) - -(defun make-compatible-variable (var new) - "Make the byte-compiler know that VARIABLE is provided for compatibility. -and NEW should be used instead. If NEW is a string, then that is the -`use instead' message." - (interactive - (list - (let ((str (completing-read "Make variable compatible: " - obarray 'boundp t))) - (if (equal str "") (error "")) - (intern str)) - (car (read-from-string (read-string "Compatible replacement: "))))) - (put var 'byte-compatible-variable new) - var) - -(put 'dont-compile 'lisp-indent-hook 0) -(defmacro dont-compile (&rest body) - "Like `progn', but the body always runs interpreted (not compiled). -If you think you need this, you're probably making a mistake somewhere." - (list 'eval (list 'quote (if (cdr body) (cons 'progn body) (car body))))) - - -;;; interface to evaluating things at compile time and/or load time -;;; these macro must come after any uses of them in this file, as their -;;; definition in the file overrides the magic definitions on the -;;; byte-compile-macro-environment. - -(put 'eval-when-compile 'lisp-indent-hook 0) -(defmacro eval-when-compile (&rest body) - "Like `progn', but evaluates the body at compile time. -The result of the body appears to the compiler as a quoted constant." - ;; Not necessary because we have it in b-c-initial-macro-environment - ;; (list 'quote (eval (cons 'progn body))) - (cons 'progn body)) - -(put 'eval-and-compile 'lisp-indent-hook 0) -(defmacro eval-and-compile (&rest body) - "Like `progn', but evaluates the body at compile time and at load time." - ;; Remember, it's magic. - (cons 'progn body)) - -;;; From Emacs 20. -(put 'eval-when-feature 'lisp-indent-hook 1) -(defmacro eval-when-feature (feature &rest body) - "Run the body forms when FEATURE is featurep, be it now or later. -Called (eval-when-feature (FEATURE [. FILENAME]) BODYFORMS...). -If (featurep 'FEATURE), evals now; otherwise adds an elt to -`after-load-alist' (which see), using FEATURE as filename if FILENAME is nil." - (let ((file (or (cdr feature) (symbol-name (car feature))))) - `(let ((bodythunk (function (lambda () ,@body)))) - (if (featurep ',(car feature)) - (funcall bodythunk) - (setq after-load-alist (cons '(,file . (list 'lambda '() bodythunk)) - after-load-alist)))))) - - - -;;; Interface to file-local byte-compiler parameters. -;;; Redefined in bytecomp.el. - -;;; The great RMS speaketh: -;;; -;;; I nuked this because it's not a good idea for users to think of -;;; using it. These options are a matter of installation preference, -;;; and have nothing to do with particular source files; it's a -;;; mistake to suggest to users that they should associate these with -;;; particular source files. There is hardly any reason to change -;;; these parameters, anyway. --rms. -;;; -;;; But I'll leave this stuff alone. --ben - -(put 'byte-compiler-options 'lisp-indent-hook 0) -(defmacro byte-compiler-options (&rest args) - "Set some compilation-parameters for this file. -This will affect only the file in which it appears; this does nothing when -evaluated, or when loaded from a .el file. - -Each argument to this macro must be a list of a key and a value. - - Keys: Values: Corresponding variable: - - verbose t, nil byte-compile-verbose - optimize t, nil, source, byte byte-optimize - warnings list of warnings byte-compile-warnings - file-format emacs19, emacs20 byte-compile-emacs19-compatibility - -The value specified with the `warnings' option must be a list, containing -some subset of the following flags: - - free-vars references to variables not in the current lexical scope. - unused-vars references to non-global variables bound but not referenced. - unresolved calls to unknown functions. - callargs lambda calls with args that don't match the definition. - redefine function cell redefined from a macro to a lambda or vice - versa, or redefined to take a different number of arguments. - -If the first element if the list is `+' or `-' then the specified elements -are added to or removed from the current set of warnings, instead of the -entire set of warnings being overwritten. - -For example, something like this might appear at the top of a source file: - - (byte-compiler-options - (optimize t) - (warnings (- callargs)) ; Don't warn about arglist mismatch - (warnings (+ unused-vars)) ; Do warn about unused bindings - (file-format emacs19))" - nil) - -;;; bytecomp-runtime.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp/bytecomp.el --- a/lisp/bytecomp/bytecomp.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4100 +0,0 @@ -;;; bytecomp.el --- compilation of Lisp code into byte code. - -;;; Copyright (C) 1985-1987, 1991-1994 Free Software Foundation, Inc. -;;; Copyright (C) 1996 Ben Wing. - -;; Author: Jamie Zawinski -;; Hallvard Furuseth -;; Keywords: internal - -;; Subsequently modified by RMS and others. - -(defconst byte-compile-version (purecopy "2.25 XEmacs; 22-Mar-96.")) - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;; The Emacs Lisp byte compiler. This crunches lisp source into a sort -;; of p-code which takes up less space and can be interpreted faster. -;; The user entry points are byte-compile-file and byte-recompile-directory. - -;;; Code: - -;;; ======================================================================== -;;; Entry points: -;;; byte-recompile-directory, byte-compile-file, -;;; batch-byte-compile, batch-byte-recompile-directory, -;;; byte-compile, compile-defun, -;;; display-call-tree -;;; RMS says: -;;; (byte-compile-buffer and byte-compile-and-load-file were turned off -;;; because they are not terribly useful and get in the way of completion.) -;;; But I'm leaving them. --ben - -;;; This version of the byte compiler has the following improvements: -;;; + optimization of compiled code: -;;; - removal of unreachable code; -;;; - removal of calls to side-effectless functions whose return-value -;;; is unused; -;;; - compile-time evaluation of safe constant forms, such as (consp nil) -;;; and (ash 1 6); -;;; - open-coding of literal lambdas; -;;; - peephole optimization of emitted code; -;;; - trivial functions are left uncompiled for speed. -;;; + support for inline functions; -;;; + compile-time evaluation of arbitrary expressions; -;;; + compile-time warning messages for: -;;; - functions being redefined with incompatible arglists; -;;; - functions being redefined as macros, or vice-versa; -;;; - functions or macros defined multiple times in the same file; -;;; - functions being called with the incorrect number of arguments; -;;; - functions being called which are not defined globally, in the -;;; file, or as autoloads; -;;; - assignment and reference of undeclared free variables; -;;; - various syntax errors; -;;; + correct compilation of nested defuns, defmacros, defvars and defsubsts; -;;; + correct compilation of top-level uses of macros; -;;; + the ability to generate a histogram of functions called. - -;;; User customization variables: -;;; -;;; byte-compile-verbose Whether to report the function currently being -;;; compiled in the minibuffer; -;;; byte-optimize Whether to do optimizations; this may be -;;; t, nil, 'source, or 'byte; -;;; byte-optimize-log Whether to report (in excruciating detail) -;;; exactly which optimizations have been made. -;;; This may be t, nil, 'source, or 'byte; -;;; byte-compile-error-on-warn Whether to stop compilation when a warning is -;;; produced; -;;; byte-compile-delete-errors Whether the optimizer may delete calls or -;;; variable references that are side-effect-free -;;; except that they may return an error. -;;; byte-compile-generate-call-tree Whether to generate a histogram of -;;; function calls. This can be useful for -;;; finding unused functions, as well as simple -;;; performance metering. -;;; byte-compile-warnings List of warnings to issue, or t. May contain -;;; 'free-vars (references to variables not in the -;;; current lexical scope) -;;; 'unused-vars (non-global variables bound but -;;; not referenced) -;;; 'unresolved (calls to unknown functions) -;;; 'callargs (lambda calls with args that don't -;;; match the lambda's definition) -;;; 'redefine (function cell redefined from -;;; a macro to a lambda or vice versa, -;;; or redefined to take other args) -;;; 'obsolete (obsolete variables and functions) -;;; 'pedantic (references to Emacs-compatible -;;; symbols) -;;; byte-compile-emacs19-compatibility Whether the compiler should -;;; generate .elc files which can be loaded into -;;; generic emacs 19. -;;; emacs-lisp-file-regexp Regexp for the extension of source-files; -;;; see also the function byte-compile-dest-file. -;;; byte-compile-overwrite-file If nil, delete old .elc files before saving. -;;; -;;; Most of the above parameters can also be set on a file-by-file basis; see -;;; the documentation of the `byte-compiler-options' macro. - -;;; New Features: -;;; -;;; o The form `defsubst' is just like `defun', except that the function -;;; generated will be open-coded in compiled code which uses it. This -;;; means that no function call will be generated, it will simply be -;;; spliced in. Lisp functions calls are very slow, so this can be a -;;; big win. -;;; -;;; You can generally accomplish the same thing with `defmacro', but in -;;; that case, the defined procedure can't be used as an argument to -;;; mapcar, etc. -;;; -;;; o You can make a given function be inline even if it has already been -;;; defined with `defun' by using the `proclaim-inline' form like so: -;;; (proclaim-inline my-function) -;;; This is, in fact, exactly what `defsubst' does. To make a function no -;;; longer be inline, you must use `proclaim-notinline'. Beware that if -;;; you define a function with `defsubst' and later redefine it with -;;; `defun', it will still be open-coded until you use proclaim-notinline. -;;; -;;; o You can also open-code one particular call to a function without -;;; open-coding all calls. Use the 'inline' form to do this, like so: -;;; -;;; (inline (foo 1 2 3)) ;; `foo' will be open-coded -;;; or... -;;; (inline ;; `foo' and `baz' will be -;;; (foo 1 2 3 (bar 5)) ;; open-coded, but `bar' will not. -;;; (baz 0)) -;;; -;;; o It is possible to open-code a function in the same file it is defined -;;; in without having to load that file before compiling it. the -;;; byte-compiler has been modified to remember function definitions in -;;; the compilation environment in the same way that it remembers macro -;;; definitions. -;;; -;;; o Forms like ((lambda ...) ...) are open-coded. -;;; -;;; o The form `eval-when-compile' is like progn, except that the body -;;; is evaluated at compile-time. When it appears at top-level, this -;;; is analogous to the Common Lisp idiom (eval-when (compile) ...). -;;; When it does not appear at top-level, it is similar to the -;;; Common Lisp #. reader macro (but not in interpreted code). -;;; -;;; o The form `eval-and-compile' is similar to eval-when-compile, but -;;; the whole form is evalled both at compile-time and at run-time. -;;; -;;; o The command M-x byte-compile-and-load-file does what you'd think. -;;; -;;; o The command compile-defun is analogous to eval-defun. -;;; -;;; o If you run byte-compile-file on a filename which is visited in a -;;; buffer, and that buffer is modified, you are asked whether you want -;;; to save the buffer before compiling. -;;; -;;; o You can add this to /etc/magic to make file(1) recognise the files -;;; generated by this compiler: -;;; -;;; 0 string ;ELC GNU Emacs Lisp compiled file, -;;; >4 byte x version %d -;;; -;;; TO DO: -;;; -;;; o Should implement declarations and proclamations, notably special, -;;; unspecial, and ignore. Do this in such a way as to not break cl.el. -;;; o The bound-but-not-used warnings are not issued for variables whose -;;; bindings were established in the arglist, due to the lack of an -;;; ignore declaration. Once ignore exists, this should be turned on. -;;; o Warn about functions and variables defined but not used? -;;; Maybe add some kind of `export' declaration for this? -;;; (With interactive functions being automatically exported?) -;;; o Any reference to a variable, even one which is a no-op, will cause -;;; the warning not to be given. Possibly we could use the for-effect -;;; flag to determine when this reference is useless; possibly more -;;; complex flow analysis would be necessary. -;;; o If the optimizer deletes a variable reference, we might be left with -;;; a bound-but-not-referenced warning. Generally this is ok, but not if -;;; it's a synergistic result of macroexpansion. Need some way to note -;;; that a varref is being optimized away? Of course it would be nice to -;;; optimize away the binding too, someday, but it's unsafe today. -;;; o (See byte-optimize.el for the optimization TODO list.) - -(require 'backquote) - -(or (fboundp 'defsubst) - ;; This really ought to be loaded already! - (load-library "bytecomp-runtime")) - -(eval-when-compile - (defvar byte-compile-single-version nil - "If this is true, the choice of emacs version (v19 or v20) byte-codes will -be hard-coded into bytecomp when it compiles itself. If the compiler itself -is compiled with optimization, this causes a speedup.") - - (cond (byte-compile-single-version - (defmacro byte-compile-single-version () t) - (defmacro byte-compile-version-cond (cond) (list 'quote (eval cond)))) - (t - (defmacro byte-compile-single-version () nil) - (defmacro byte-compile-version-cond (cond) cond))) - ) - -(defvar emacs-lisp-file-regexp (if (eq system-type 'vax-vms) - (purecopy "\\.EL\\(;[0-9]+\\)?$") - (purecopy "\\.el$")) - "*Regexp which matches Emacs Lisp source files. -You may want to redefine `byte-compile-dest-file' if you change this.") - -;; This enables file name handlers such as jka-compr -;; to remove parts of the file name that should not be copied -;; through to the output file name. -(defun byte-compiler-base-file-name (filename) - (let ((handler (find-file-name-handler filename - 'byte-compiler-base-file-name))) - (if handler - (funcall handler 'byte-compiler-base-file-name filename) - filename))) - -(or (fboundp 'byte-compile-dest-file) - ;; The user may want to redefine this along with emacs-lisp-file-regexp, - ;; so only define it if it is undefined. - (defun byte-compile-dest-file (filename) - "Convert an Emacs Lisp source file name to a compiled file name." - (setq filename (byte-compiler-base-file-name filename)) - (setq filename (file-name-sans-versions filename)) - (cond ((eq system-type 'vax-vms) - (concat (substring filename 0 (string-match ";" filename)) "c")) - ((string-match emacs-lisp-file-regexp filename) - (concat (substring filename 0 (match-beginning 0)) ".elc")) - (t (concat filename ".elc"))))) - -;; This can be the 'byte-compile property of any symbol. -(autoload 'byte-compile-inline-expand "byte-optimize") - -;; This is the entrypoint to the lapcode optimizer pass1. -(autoload 'byte-optimize-form "byte-optimize") -;; This is the entrypoint to the lapcode optimizer pass2. -(autoload 'byte-optimize-lapcode "byte-optimize") -(autoload 'byte-compile-unfold-lambda "byte-optimize") - -;; This is the entry point to the decompiler, which is used by the -;; disassembler. The disassembler just requires 'byte-compile, but -;; that doesn't define this function, so this seems to be a reasonable -;; thing to do. -(autoload 'byte-decompile-bytecode "byte-opt") - -(defvar byte-compile-verbose - (and (not noninteractive) (> (device-baud-rate) search-slow-speed)) - "*Non-nil means print messages describing progress of byte-compiler.") - -(defvar byte-compile-emacs19-compatibility - (not (emacs-version>= 20)) - "*Non-nil means generate output that can run in Emacs 19.") - -(defvar byte-optimize t - "*Enables optimization in the byte compiler. -nil means don't do any optimization. -t means do all optimizations. -`source' means do source-level optimizations only. -`byte' means do code-level optimizations only.") - -(defvar byte-compile-delete-errors t - "*If non-nil, the optimizer may delete forms that may signal an error. -This includes variable references and calls to functions such as `car'.") - -;; XEmacs addition -(defvar byte-compile-new-bytecodes nil - "This is completely ignored. It is only around for backwards -compatibility.") - - -;; FSF enables byte-compile-dynamic-docstrings but not byte-compile-dynamic -;; by default. This would be a reasonable conservative approach except -;; for the fact that if you enable either of these, you get incompatible -;; byte code that can't be read by XEmacs 19.13 or before or FSF 19.28 or -;; before. -;; -;; Therefore, neither is enabled for 19.14. Both are enabled for 20.0 -;; because we have no reason to be conservative about changing the -;; way things work. (Ben) - -;; However, I don't think that defaulting byte-compile-dynamic to nil -;; is a compatibility issue - rather it is a performance issue. -;; Therefore I am setting byte-compile-dynamic back to nil. (mrb) - -(defvar byte-compile-dynamic nil - "*If non-nil, compile function bodies so they load lazily. -They are hidden comments in the compiled file, and brought into core when the -function is called. - -To enable this option, make it a file-local variable -in the source file you want it to apply to. -For example, add -*-byte-compile-dynamic: t;-*- on the first line. - -When this option is true, if you load the compiled file and then move it, -the functions you loaded will not be able to run.") - -(defvar byte-compile-dynamic-docstrings (emacs-version>= 20) - "*If non-nil, compile doc strings for lazy access. -We bury the doc strings of functions and variables -inside comments in the file, and bring them into core only when they -are actually needed. - -When this option is true, if you load the compiled file and then move it, -you won't be able to find the documentation of anything in that file. - -To disable this option for a certain file, make it a file-local variable -in the source file. For example, add this to the first line: - -*-byte-compile-dynamic-docstrings:nil;-*- -You can also set the variable globally. - -This option is enabled by default because it reduces Emacs memory usage.") - -(defvar byte-optimize-log nil - "*If true, the byte-compiler will log its optimizations into *Compile-Log*. -If this is 'source, then only source-level optimizations will be logged. -If it is 'byte, then only byte-level optimizations will be logged.") - -(defvar byte-compile-error-on-warn nil - "*If true, the byte-compiler reports warnings with `error'.") - -;; byte-compile-warning-types in FSF. -(defvar byte-compile-default-warnings - '(redefine callargs free-vars unresolved unused-vars obsolete) - "*The warnings used when byte-compile-warnings is t.") - -(defvar byte-compile-warnings t - "*List of warnings that the compiler should issue (t for the default set). -Elements of the list may be: - - free-vars references to variables not in the current lexical scope. - unused-vars references to non-global variables bound but not referenced. - unresolved calls to unknown functions. - callargs lambda calls with args that don't match the definition. - redefine function cell redefined from a macro to a lambda or vice - versa, or redefined to take a different number of arguments. - obsolete use of an obsolete function or variable. - pedantic warn of use of compatible symbols. - -The default set is specified by `byte-compile-default-warnings' and -normally encompasses all possible warnings. - -See also the macro `byte-compiler-options'.") - -(defvar byte-compile-generate-call-tree nil - "*Non-nil means collect call-graph information when compiling. -This records functions were called and from where. -If the value is t, compilation displays the call graph when it finishes. -If the value is neither t nor nil, compilation asks you whether to display -the graph. - -The call tree only lists functions called, not macros used. Those functions -which the byte-code interpreter knows about directly (eq, cons, etc.) are -not reported. - -The call tree also lists those functions which are not known to be called -\(that is, to which no calls have been compiled). Functions which can be -invoked interactively are excluded from this list.") - -(defconst byte-compile-call-tree nil "Alist of functions and their call tree. -Each element looks like - - \(FUNCTION CALLERS CALLS\) - -where CALLERS is a list of functions that call FUNCTION, and CALLS -is a list of functions for which calls were generated while compiling -FUNCTION.") - -(defvar byte-compile-call-tree-sort 'name - "*If non-nil, sort the call tree. -The values `name', `callers', `calls', `calls+callers' -specify different fields to sort on.") - -(defvar byte-compile-overwrite-file t - "If nil, old .elc files are deleted before the new is saved, and .elc -files will have the same modes as the corresponding .el file. Otherwise, -existing .elc files will simply be overwritten, and the existing modes -will not be changed. If this variable is nil, then an .elc file which -is a symbolic link will be turned into a normal file, instead of the file -which the link points to being overwritten.") - -(defvar byte-recompile-directory-ignore-errors-p nil - "If true, then `byte-recompile-directory' will continue compiling even -when an error occurs in a file. This is bound to t by -`batch-byte-recompile-directory'.") - -(defvar byte-recompile-directory-recursively t - "*If true, then `byte-recompile-directory' will recurse on subdirectories.") - -(defvar byte-compile-constants nil - "list of all constants encountered during compilation of this form") -(defvar byte-compile-variables nil - "list of all variables encountered during compilation of this form") -(defvar byte-compile-bound-variables nil - "Alist of variables bound in the context of the current form, -that is, the current lexical environment. This list lives partly -on the specbind stack. The cdr of each cell is an integer bitmask.") - -(defconst byte-compile-referenced-bit 1) -(defconst byte-compile-assigned-bit 2) -(defconst byte-compile-arglist-bit 4) -(defconst byte-compile-global-bit 8) - -(defvar byte-compile-free-references) -(defvar byte-compile-free-assignments) - -(defvar byte-compiler-error-flag) - -(defconst byte-compile-initial-macro-environment - (purecopy - '((byte-compiler-options . (lambda (&rest forms) - (apply 'byte-compiler-options-handler forms))) - (eval-when-compile . (lambda (&rest body) - (list 'quote (eval (byte-compile-top-level - (cons 'progn body)))))) - (eval-and-compile . (lambda (&rest body) - (eval (cons 'progn body)) - (cons 'progn body))))) - "The default macro-environment passed to macroexpand by the compiler. -Placing a macro here will cause a macro to have different semantics when -expanded by the compiler as when expanded by the interpreter.") - -(defvar byte-compile-macro-environment byte-compile-initial-macro-environment - "Alist of macros defined in the file being compiled. -Each element looks like (MACRONAME . DEFINITION). It is -\(MACRONAME . nil) when a macro is redefined as a function.") - -(defvar byte-compile-function-environment nil - "Alist of functions defined in the file being compiled. -This is so we can inline them when necessary. -Each element looks like (FUNCTIONNAME . DEFINITION). It is -\(FUNCTIONNAME . nil) when a function is redefined as a macro.") - -(defvar byte-compile-autoload-environment nil - "Alist of functions and macros defined by autoload in the file being compiled. -This is so we can suppress warnings about calls to these functions, even though -they do not have `real' definitions. -Each element looks like (FUNCTIONNAME . CALL-TO-AUTOLOAD).") - -(defvar byte-compile-unresolved-functions nil - "Alist of undefined functions to which calls have been compiled (used for -warnings when the function is later defined with incorrect args).") - -(defvar byte-compile-file-domain) ; domain of file being compiled - -(defvar byte-compile-tag-number 0) -(defvar byte-compile-output nil - "Alist describing contents to put in byte code string. -Each element is (INDEX . VALUE)") -(defvar byte-compile-depth 0 "Current depth of execution stack.") -(defvar byte-compile-maxdepth 0 "Maximum depth of execution stack.") - - -;;; The byte codes; this information is duplicated in bytecode.c - -(defconst byte-code-vector nil - "An array containing byte-code names indexed by byte-code values.") - -(defconst byte-stack+-info nil - "An array with the stack adjustment for each byte-code.") - -(defmacro byte-defop (opcode stack-adjust opname &optional docstring) - ;; This is a speed-hack for building the byte-code-vector at compile-time. - ;; We fill in the vector at macroexpand-time, and then after the last call - ;; to byte-defop, we write the vector out as a constant instead of writing - ;; out a bunch of calls to aset. - ;; Actually, we don't fill in the vector itself, because that could make - ;; it problematic to compile big changes to this compiler; we store the - ;; values on its plist, and remove them later in -extrude. - (let ((v1 (or (get 'byte-code-vector 'tmp-compile-time-value) - (put 'byte-code-vector 'tmp-compile-time-value - (make-vector 256 nil)))) - (v2 (or (get 'byte-stack+-info 'tmp-compile-time-value) - (put 'byte-stack+-info 'tmp-compile-time-value - (make-vector 256 nil))))) - (aset v1 opcode opname) - (aset v2 opcode stack-adjust)) - (if docstring - (list 'defconst opname opcode (concat "Byte code opcode " docstring ".")) - (list 'defconst opname opcode))) - -(defmacro byte-extrude-byte-code-vectors () - (prog1 (list 'setq 'byte-code-vector - (get 'byte-code-vector 'tmp-compile-time-value) - 'byte-stack+-info - (get 'byte-stack+-info 'tmp-compile-time-value)) - (remprop 'byte-code-vector 'tmp-compile-time-value) - (remprop 'byte-stack+-info 'tmp-compile-time-value))) - - -;; unused: 0-7 - -;; These opcodes are special in that they pack their argument into the -;; opcode word. -;; -(byte-defop 8 1 byte-varref "for variable reference") -(byte-defop 16 -1 byte-varset "for setting a variable") -(byte-defop 24 -1 byte-varbind "for binding a variable") -(byte-defop 32 0 byte-call "for calling a function") -(byte-defop 40 0 byte-unbind "for unbinding special bindings") -;; codes 8-47 are consumed by the preceding opcodes - -;; unused: 48-55 - -(byte-defop 56 -1 byte-nth) -(byte-defop 57 0 byte-symbolp) -(byte-defop 58 0 byte-consp) -(byte-defop 59 0 byte-stringp) -(byte-defop 60 0 byte-listp) -(byte-defop 61 -1 byte-old-eq) -(byte-defop 62 -1 byte-old-memq) -(byte-defop 63 0 byte-not) -(byte-defop 64 0 byte-car) -(byte-defop 65 0 byte-cdr) -(byte-defop 66 -1 byte-cons) -(byte-defop 67 0 byte-list1) -(byte-defop 68 -1 byte-list2) -(byte-defop 69 -2 byte-list3) -(byte-defop 70 -3 byte-list4) -(byte-defop 71 0 byte-length) -(byte-defop 72 -1 byte-aref) -(byte-defop 73 -2 byte-aset) -(byte-defop 74 0 byte-symbol-value) -(byte-defop 75 0 byte-symbol-function) ; this was commented out -(byte-defop 76 -1 byte-set) -(byte-defop 77 -1 byte-fset) ; this was commented out -(byte-defop 78 -1 byte-get) -(byte-defop 79 -2 byte-substring) -(byte-defop 80 -1 byte-concat2) -(byte-defop 81 -2 byte-concat3) -(byte-defop 82 -3 byte-concat4) -(byte-defop 83 0 byte-sub1) -(byte-defop 84 0 byte-add1) -(byte-defop 85 -1 byte-eqlsign) -(byte-defop 86 -1 byte-gtr) -(byte-defop 87 -1 byte-lss) -(byte-defop 88 -1 byte-leq) -(byte-defop 89 -1 byte-geq) -(byte-defop 90 -1 byte-diff) -(byte-defop 91 0 byte-negate) -(byte-defop 92 -1 byte-plus) -(byte-defop 93 -1 byte-max) -(byte-defop 94 -1 byte-min) -(byte-defop 95 -1 byte-mult) -(byte-defop 96 1 byte-point) -(byte-defop 97 -1 byte-eq) ; new as of v20 -(byte-defop 98 0 byte-goto-char) -(byte-defop 99 0 byte-insert) -(byte-defop 100 1 byte-point-max) -(byte-defop 101 1 byte-point-min) -(byte-defop 102 0 byte-char-after) -(byte-defop 103 1 byte-following-char) -(byte-defop 104 1 byte-preceding-char) -(byte-defop 105 1 byte-current-column) -(byte-defop 106 0 byte-indent-to) -(byte-defop 107 -1 byte-equal) ; new as of v20 -(byte-defop 108 1 byte-eolp) -(byte-defop 109 1 byte-eobp) -(byte-defop 110 1 byte-bolp) -(byte-defop 111 1 byte-bobp) -(byte-defop 112 1 byte-current-buffer) -(byte-defop 113 0 byte-set-buffer) -(byte-defop 114 0 byte-save-current-buffer - "To make a binding to record the current buffer.") -;;(byte-defop 114 1 byte-read-char-OBSOLETE) ;obsolete as of v19 -(byte-defop 115 -1 byte-memq) ; new as of v20 -(byte-defop 116 1 byte-interactive-p) - -(byte-defop 117 0 byte-forward-char) -(byte-defop 118 0 byte-forward-word) -(byte-defop 119 -1 byte-skip-chars-forward) -(byte-defop 120 -1 byte-skip-chars-backward) -(byte-defop 121 0 byte-forward-line) -(byte-defop 122 0 byte-char-syntax) -(byte-defop 123 -1 byte-buffer-substring) -(byte-defop 124 -1 byte-delete-region) -(byte-defop 125 -1 byte-narrow-to-region) -(byte-defop 126 1 byte-widen) -(byte-defop 127 0 byte-end-of-line) - -;; unused: 128 - -;; These store their argument in the next two bytes -(byte-defop 129 1 byte-constant2 - "for reference to a constant with vector index >= byte-constant-limit") -(byte-defop 130 0 byte-goto "for unconditional jump") -(byte-defop 131 -1 byte-goto-if-nil "to pop value and jump if it's nil") -(byte-defop 132 -1 byte-goto-if-not-nil - "to pop value and jump if it's not nil") -(byte-defop 133 -1 byte-goto-if-nil-else-pop - "to examine top-of-stack, jump and don't pop it if it's nil, -otherwise pop it") -(byte-defop 134 -1 byte-goto-if-not-nil-else-pop - "to examine top-of-stack, jump and don't pop it if it's non nil, -otherwise pop it") - -(byte-defop 135 -1 byte-return "to pop a value and return it from `byte-code'") -(byte-defop 136 -1 byte-discard "to discard one value from stack") -(byte-defop 137 1 byte-dup "to duplicate the top of the stack") - -(byte-defop 138 0 byte-save-excursion - "to make a binding to record the buffer, point and mark") -(byte-defop 139 0 byte-save-window-excursion - "to make a binding to record entire window configuration") -(byte-defop 140 0 byte-save-restriction - "to make a binding to record the current buffer clipping restrictions") -(byte-defop 141 -1 byte-catch - "for catch. Takes, on stack, the tag and an expression for the body") -(byte-defop 142 -1 byte-unwind-protect - "for unwind-protect. Takes, on stack, an expression for the unwind-action") - -;; For condition-case. Takes, on stack, the variable to bind, -;; an expression for the body, and a list of clauses. -(byte-defop 143 -2 byte-condition-case) - -;; For entry to with-output-to-temp-buffer. -;; Takes, on stack, the buffer name. -;; Binds standard-output and does some other things. -;; Returns with temp buffer on the stack in place of buffer name. -(byte-defop 144 0 byte-temp-output-buffer-setup) - -;; For exit from with-output-to-temp-buffer. -;; Expects the temp buffer on the stack underneath value to return. -;; Pops them both, then pushes the value back on. -;; Unbinds standard-output and makes the temp buffer visible. -(byte-defop 145 -1 byte-temp-output-buffer-show) - -;; To unbind back to the beginning of this frame. -;; Not used yet, but will be needed for tail-recursion elimination. -(byte-defop 146 0 byte-unbind-all) - -(byte-defop 147 -2 byte-set-marker) -(byte-defop 148 0 byte-match-beginning) -(byte-defop 149 0 byte-match-end) -(byte-defop 150 0 byte-upcase) -(byte-defop 151 0 byte-downcase) -(byte-defop 152 -1 byte-string=) -(byte-defop 153 -1 byte-string<) -(byte-defop 154 -1 byte-old-equal) -(byte-defop 155 -1 byte-nthcdr) -(byte-defop 156 -1 byte-elt) -(byte-defop 157 -1 byte-old-member) -(byte-defop 158 -1 byte-old-assq) -(byte-defop 159 0 byte-nreverse) -(byte-defop 160 -1 byte-setcar) -(byte-defop 161 -1 byte-setcdr) -(byte-defop 162 0 byte-car-safe) -(byte-defop 163 0 byte-cdr-safe) -(byte-defop 164 -1 byte-nconc) -(byte-defop 165 -1 byte-quo) -(byte-defop 166 -1 byte-rem) -(byte-defop 167 0 byte-numberp) -(byte-defop 168 0 byte-integerp) - -;; unused: 169 - -;; These are not present in FSF. -;; -(byte-defop 170 0 byte-rel-goto) -(byte-defop 171 -1 byte-rel-goto-if-nil) -(byte-defop 172 -1 byte-rel-goto-if-not-nil) -(byte-defop 173 -1 byte-rel-goto-if-nil-else-pop) -(byte-defop 174 -1 byte-rel-goto-if-not-nil-else-pop) - -(byte-defop 175 nil byte-listN) -(byte-defop 176 nil byte-concatN) -(byte-defop 177 nil byte-insertN) - -;; unused: 178-181 - -;; these ops are new to v20 -(byte-defop 182 -1 byte-member) -(byte-defop 183 -1 byte-assq) - -;; unused: 184-191 - -(byte-defop 192 1 byte-constant "for reference to a constant") -;; codes 193-255 are consumed by byte-constant. -(defconst byte-constant-limit 64 - "Exclusive maximum index usable in the `byte-constant' opcode.") - -(defconst byte-goto-ops (purecopy - '(byte-goto byte-goto-if-nil byte-goto-if-not-nil - byte-goto-if-nil-else-pop - byte-goto-if-not-nil-else-pop)) - "List of byte-codes whose offset is a pc.") - -(defconst byte-goto-always-pop-ops - (purecopy '(byte-goto-if-nil byte-goto-if-not-nil))) - -(defconst byte-rel-goto-ops - (purecopy '(byte-rel-goto byte-rel-goto-if-nil byte-rel-goto-if-not-nil - byte-rel-goto-if-nil-else-pop byte-rel-goto-if-not-nil-else-pop)) - "byte-codes for relative jumps.") - -(byte-extrude-byte-code-vectors) - -;;; lapcode generator -;;; -;;; the byte-compiler now does source -> lapcode -> bytecode instead of -;;; source -> bytecode, because it's a lot easier to make optimizations -;;; on lapcode than on bytecode. -;;; -;;; Elements of the lapcode list are of the form ( . ) -;;; where instruction is a symbol naming a byte-code instruction, -;;; and parameter is an argument to that instruction, if any. -;;; -;;; The instruction can be the pseudo-op TAG, which means that this position -;;; in the instruction stream is a target of a goto. (car PARAMETER) will be -;;; the PC for this location, and the whole instruction "(TAG pc)" will be the -;;; parameter for some goto op. -;;; -;;; If the operation is varbind, varref, varset or push-constant, then the -;;; parameter is (variable/constant . index_in_constant_vector). -;;; -;;; First, the source code is macroexpanded and optimized in various ways. -;;; Then the resultant code is compiled into lapcode. Another set of -;;; optimizations are then run over the lapcode. Then the variables and -;;; constants referenced by the lapcode are collected and placed in the -;;; constants-vector. (This happens now so that variables referenced by dead -;;; code don't consume space.) And finally, the lapcode is transformed into -;;; compacted byte-code. -;;; -;;; A distinction is made between variables and constants because the variable- -;;; referencing instructions are more sensitive to the variables being near the -;;; front of the constants-vector than the constant-referencing instructions. -;;; Also, this lets us notice references to free variables. - -(defun byte-compile-lapcode (lap) - "Turns lapcode into bytecode. The lapcode is destroyed." - ;; Lapcode modifications: changes the ID of a tag to be the tag's PC. - (let ((pc 0) ; Program counter - op off ; Operation & offset - (bytes '()) ; Put the output bytes here - (patchlist nil) ; List of tags and goto's to patch - rest rel tmp) - (while lap - (setq op (car (car lap)) - off (cdr (car lap))) - (cond ((not (symbolp op)) - (error "Non-symbolic opcode `%s'" op)) - ((eq op 'TAG) - (setcar off pc) - (setq patchlist (cons off patchlist))) - ((memq op byte-goto-ops) - (setq pc (+ pc 3)) - (setq bytes (cons (cons pc (cdr off)) - (cons nil - (cons (symbol-value op) bytes)))) - (setq patchlist (cons bytes patchlist))) - (t - (setq bytes - (cond ((cond ((consp off) - ;; Variable or constant reference - (setq off (cdr off)) - (eq op 'byte-constant))) - (cond ((< off byte-constant-limit) - (setq pc (1+ pc)) - (cons (+ byte-constant off) bytes)) - (t - (setq pc (+ 3 pc)) - (cons (lsh off -8) - (cons (logand off 255) - (cons byte-constant2 bytes)))))) - ((and (<= byte-listN (symbol-value op)) - (<= (symbol-value op) byte-insertN)) - (setq pc (+ 2 pc)) - (cons off (cons (symbol-value op) bytes))) - ((< off 6) - (setq pc (1+ pc)) - (cons (+ (symbol-value op) off) bytes)) - ((< off 256) - (setq pc (+ 2 pc)) - (cons off (cons (+ (symbol-value op) 6) bytes))) - (t - (setq pc (+ 3 pc)) - (cons (lsh off -8) - (cons (logand off 255) - (cons (+ (symbol-value op) 7) - bytes)))))))) - (setq lap (cdr lap))) - ;;(if (not (= pc (length bytes))) - ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes))) - (cond (t ;; starting with Emacs 19. - ;; Make relative jumps - (setq patchlist (nreverse patchlist)) - (while (progn - (setq off 0) ; PC change because of deleted bytes - (setq rest patchlist) - (while rest - (setq tmp (car rest)) - (and (consp (car tmp)) ; Jump - (prog1 (null (nth 1 tmp)) ; Absolute jump - (setq tmp (car tmp))) - (progn - (setq rel (- (car (cdr tmp)) (car tmp))) - (and (<= -129 rel) (< rel 128))) - (progn - ;; Convert to relative jump. - (setcdr (car rest) (cdr (cdr (car rest)))) - (setcar (cdr (car rest)) - (+ (car (cdr (car rest))) - (- byte-rel-goto byte-goto))) - (setq off (1- off)))) - (setcar tmp (+ (car tmp) off)) ; Adjust PC - (setq rest (cdr rest))) - ;; If optimizing, repeat until no change. - (and byte-optimize - (not (zerop off))))))) - ;; Patch PC into jumps - (let (bytes) - (while patchlist - (setq bytes (car patchlist)) - (cond ((atom (car bytes))) ; Tag - ((nth 1 bytes) ; Relative jump - (setcar bytes (+ (- (car (cdr (car bytes))) (car (car bytes))) - 128))) - (t ; Absolute jump - (setq pc (car (cdr (car bytes)))) ; Pick PC from tag - (setcar (cdr bytes) (logand pc 255)) - (setcar bytes (lsh pc -8)))) - (setq patchlist (cdr patchlist)))) - (concat (nreverse bytes)))) - - -;;; byte compiler messages - -(defvar byte-compile-current-form nil) -(defvar byte-compile-current-file nil) -(defvar byte-compile-dest-file nil) - -(defmacro byte-compile-log (format-string &rest args) - (list 'and - 'byte-optimize - '(memq byte-optimize-log '(t source)) - (list 'let '((print-escape-newlines t) - (print-level 4) - (print-length 4)) - (list 'byte-compile-log-1 - (cons 'format - (cons format-string - (mapcar - '(lambda (x) - (if (symbolp x) (list 'prin1-to-string x) x)) - args))))))) - -(defconst byte-compile-last-warned-form nil) - -;; Log a message STRING in *Compile-Log*. -;; Also log the current function and file if not already done. -(defun byte-compile-log-1 (string &optional fill) - (let ((this-form (or byte-compile-current-form "toplevel forms"))) - (cond - (noninteractive - (if (or byte-compile-current-file - (and byte-compile-last-warned-form - (not (eq this-form byte-compile-last-warned-form)))) - (message - (format "While compiling %s%s:" - this-form - (if byte-compile-current-file - (if (stringp byte-compile-current-file) - (concat " in file " byte-compile-current-file) - (concat " in buffer " - (buffer-name byte-compile-current-file))) - "")))) - (message " %s" string)) - (t - (save-excursion - (set-buffer (get-buffer-create "*Compile-Log*")) - (goto-char (point-max)) - (cond ((or byte-compile-current-file - (and byte-compile-last-warned-form - (not (eq this-form byte-compile-last-warned-form)))) - (if byte-compile-current-file - (insert "\n\^L\n" (current-time-string) "\n")) - (insert "While compiling " - (if (stringp this-form) this-form - (format "%s" this-form))) - (if byte-compile-current-file - (if (stringp byte-compile-current-file) - (insert " in file " byte-compile-current-file) - (insert " in buffer " - (buffer-name byte-compile-current-file)))) - (insert ":\n"))) - (insert " " string "\n") - (if (and fill (not (string-match "\n" string))) - (let ((fill-prefix " ") - (fill-column 78)) - (fill-paragraph nil))) - ))) - (setq byte-compile-current-file nil - byte-compile-last-warned-form this-form))) - -;; Log the start of a file in *Compile-Log*, and mark it as done. -;; But do nothing in batch mode. -(defun byte-compile-log-file () - (and byte-compile-current-file (not noninteractive) - (save-excursion - (set-buffer (get-buffer-create "*Compile-Log*")) - (goto-char (point-max)) - (insert "\n\^L\nCompiling " - (if (stringp byte-compile-current-file) - (concat "file " byte-compile-current-file) - (concat "buffer " (buffer-name byte-compile-current-file))) - " at " (current-time-string) "\n") - (setq byte-compile-current-file nil)))) - -(defun byte-compile-warn (format &rest args) - (setq format (apply 'format format args)) - (if byte-compile-error-on-warn - (error "%s" format) ; byte-compile-file catches and logs it - (byte-compile-log-1 (concat "** " format) t) -;;; RMS says: -;;; It is useless to flash warnings too fast to be read. -;;; Besides, they will all be shown at the end. -;;; and comments out the next two lines. - (or noninteractive ; already written on stdout. - (message "Warning: %s" format)))) - -;;; This function should be used to report errors that have halted -;;; compilation of the current file. -(defun byte-compile-report-error (error-info) - (setq byte-compiler-error-flag t) - (byte-compile-log-1 - (concat "!! " - (format (if (cdr error-info) "%s (%s)" "%s") - (get (car error-info) 'error-message) - (prin1-to-string (cdr error-info)))))) - -;;; Used by make-obsolete. -(defun byte-compile-obsolete (form) - (let ((new (get (car form) 'byte-obsolete-info))) - (if (memq 'obsolete byte-compile-warnings) - (byte-compile-warn "%s is an obsolete function; %s" (car form) - (if (stringp (car new)) - (car new) - (format "use %s instead." (car new))))) - (funcall (or (cdr new) 'byte-compile-normal-call) form))) - -;;; Used by make-obsolete. -(defun byte-compile-compatible (form) - (let ((new (get (car form) 'byte-compatible-info))) - (if (memq 'pedantic byte-compile-warnings) - (byte-compile-warn "%s is provided for compatibility; %s" (car form) - (if (stringp (car new)) - (car new) - (format "use %s instead." (car new))))) - (funcall (or (cdr new) 'byte-compile-normal-call) form))) - -;; Compiler options - -(defconst byte-compiler-legal-options - '((optimize byte-optimize (t nil source byte) val) - (file-format byte-compile-emacs19-compatibility (emacs19 emacs20) - (eq val 'emacs19)) - (delete-errors byte-compile-delete-errors (t nil) val) - (verbose byte-compile-verbose (t nil) val) - (new-bytecodes byte-compile-new-bytecodes (t nil) val) - (warnings byte-compile-warnings - ((callargs redefine free-vars unused-vars unresolved)) - val))) - -;; XEmacs addition -(defconst byte-compiler-obsolete-options - '((new-bytecodes t))) - -;; Inhibit v19/v20 selectors if the version is hardcoded. -;; #### This should print a warning if the user tries to change something -;; than can't be changed because the running compiler doesn't support it. -(cond - ((byte-compile-single-version) - (setcar (cdr (cdr (assq 'file-format byte-compiler-legal-options))) - (if (byte-compile-version-cond byte-compile-emacs19-compatibility) - '(emacs19) '(emacs20))))) - -;; now we can copy it. -(setq byte-compiler-legal-options (purecopy byte-compiler-legal-options)) - -(defun byte-compiler-options-handler (&rest args) - (let (key val desc choices) - (while args - (if (or (atom (car args)) (nthcdr 2 (car args)) (null (cdr (car args)))) - (error "malformed byte-compiler-option %s" (car args))) - (setq key (car (car args)) - val (car (cdr (car args))) - desc (assq key byte-compiler-legal-options)) - (or desc - (error "unknown byte-compiler option %s" key)) - (if (assq key byte-compiler-obsolete-options) - (byte-compile-warn "%s is an obsolete byte-compiler option." key)) - (setq choices (nth 2 desc)) - (if (consp (car choices)) - (let* (this - (handler 'cons) - (var (nth 1 desc)) - (ret (and (memq (car val) '(+ -)) - (copy-sequence (if (eq t (symbol-value var)) - (car choices) - (symbol-value var)))))) - (setq choices (car choices)) - (while val - (setq this (car val)) - (cond ((memq this choices) - (setq ret (funcall handler this ret))) - ((eq this '+) (setq handler 'cons)) - ((eq this '-) (setq handler 'delq)) - ((error "%s only accepts %s." key choices))) - (setq val (cdr val))) - (set (nth 1 desc) ret)) - (or (memq val choices) - (error "%s must be one of %s." key choices)) - (set (nth 1 desc) (eval (nth 3 desc)))) - (setq args (cdr args))) - nil)) - -;;; sanity-checking arglists - -(defun byte-compile-fdefinition (name macro-p) - (let* ((list (if (memq macro-p '(nil subr)) - byte-compile-function-environment - byte-compile-macro-environment)) - (env (cdr (assq name list)))) - (or env - (let ((fn name)) - (while (and (symbolp fn) - (fboundp fn) - (or (symbolp (symbol-function fn)) - (consp (symbol-function fn)) - (and (not macro-p) - (compiled-function-p (symbol-function fn))) - (and (eq macro-p 'subr) (subrp fn)))) - (setq fn (symbol-function fn))) - (if (or (and (not macro-p) (compiled-function-p fn)) - (and (eq macro-p 'subr) (subrp fn))) - fn - (and (consp fn) - (not (eq macro-p 'subr)) - (if (eq 'macro (car fn)) - (cdr fn) - (if macro-p - nil - (if (eq 'autoload (car fn)) - nil - fn))))))))) - -(defun byte-compile-arglist-signature (arglist) - (let ((args 0) - opts - restp) - (while arglist - (cond ((eq (car arglist) '&optional) - (or opts (setq opts 0))) - ((eq (car arglist) '&rest) - (if (cdr arglist) - (setq restp t - arglist nil))) - (t - (if opts - (setq opts (1+ opts)) - (setq args (1+ args))))) - (setq arglist (cdr arglist))) - (cons args (if restp nil (if opts (+ args opts) args))))) - - -(defun byte-compile-arglist-signatures-congruent-p (old new) - (not (or - (> (car new) (car old)) ; requires more args now - (and (null (cdr old)) ; tooks rest-args, doesn't any more - (cdr new)) - (and (cdr new) (cdr old) ; can't take as many args now - (< (cdr new) (cdr old))) - ))) - -(defun byte-compile-arglist-signature-string (signature) - (cond ((null (cdr signature)) - (format "%d+" (car signature))) - ((= (car signature) (cdr signature)) - (format "%d" (car signature))) - (t (format "%d-%d" (car signature) (cdr signature))))) - - -;; Warn if the form is calling a function with the wrong number of arguments. -(defun byte-compile-callargs-warn (form) - (let* ((def (or (byte-compile-fdefinition (car form) nil) - (byte-compile-fdefinition (car form) t))) - (sig (and def (byte-compile-arglist-signature - (if (eq 'lambda (car-safe def)) - (nth 1 def) - (if (compiled-function-p def) - (compiled-function-arglist def) - '(&rest def)))))) - (ncall (length (cdr form)))) - (if (and (null def) - (fboundp 'subr-min-args) - (setq def (byte-compile-fdefinition (car form) 'subr))) - (setq sig (cons (subr-min-args def) (subr-max-args def)))) - (if sig - (if (or (< ncall (car sig)) - (and (cdr sig) (> ncall (cdr sig)))) - (byte-compile-warn - "%s called with %d argument%s, but %s %s" - (car form) ncall - (if (= 1 ncall) "" "s") - (if (< ncall (car sig)) - "requires" - "accepts only") - (byte-compile-arglist-signature-string sig))) - (or (fboundp (car form)) ; might be a subr or autoload. - ;; ## this doesn't work with recursion. - (eq (car form) byte-compile-current-form) - ;; It's a currently-undefined function. - ;; Remember number of args in call. - (let ((cons (assq (car form) byte-compile-unresolved-functions)) - (n (length (cdr form)))) - (if cons - (or (memq n (cdr cons)) - (setcdr cons (cons n (cdr cons)))) - (setq byte-compile-unresolved-functions - (cons (list (car form) n) - byte-compile-unresolved-functions)))))))) - -;; Warn if the function or macro is being redefined with a different -;; number of arguments. -(defun byte-compile-arglist-warn (form macrop) - (let ((old (byte-compile-fdefinition (nth 1 form) macrop))) - (if old - (let ((sig1 (byte-compile-arglist-signature - (if (eq 'lambda (car-safe old)) - (nth 1 old) - (if (compiled-function-p old) - (compiled-function-arglist old) - '(&rest def))))) - (sig2 (byte-compile-arglist-signature (nth 2 form)))) - (or (byte-compile-arglist-signatures-congruent-p sig1 sig2) - (byte-compile-warn "%s %s used to take %s %s, now takes %s" - (if (eq (car form) 'defun) "function" "macro") - (nth 1 form) - (byte-compile-arglist-signature-string sig1) - (if (equal sig1 '(1 . 1)) "argument" "arguments") - (byte-compile-arglist-signature-string sig2)))) - ;; This is the first definition. See if previous calls are compatible. - (let ((calls (assq (nth 1 form) byte-compile-unresolved-functions)) - nums sig min max) - (if calls - (progn - (setq sig (byte-compile-arglist-signature (nth 2 form)) - nums (sort (copy-sequence (cdr calls)) (function <)) - min (car nums) - max (car (nreverse nums))) - (if (or (< min (car sig)) - (and (cdr sig) (> max (cdr sig)))) - (byte-compile-warn - "%s being defined to take %s%s, but was previously called with %s" - (nth 1 form) - (byte-compile-arglist-signature-string sig) - (if (equal sig '(1 . 1)) " arg" " args") - (byte-compile-arglist-signature-string (cons min max)))) - - (setq byte-compile-unresolved-functions - (delq calls byte-compile-unresolved-functions))))) - ))) - -;; If we have compiled any calls to functions which are not known to be -;; defined, issue a warning enumerating them. -;; `unresolved' in the list `byte-compile-warnings' disables this. -(defun byte-compile-warn-about-unresolved-functions (&optional msg) - (if (memq 'unresolved byte-compile-warnings) - (let ((byte-compile-current-form (or msg "the end of the data"))) - ;; First delete the autoloads from the list. - (if byte-compile-autoload-environment - (let ((rest byte-compile-unresolved-functions)) - (while rest - (if (assq (car (car rest)) byte-compile-autoload-environment) - (setq byte-compile-unresolved-functions - (delq (car rest) byte-compile-unresolved-functions))) - (setq rest (cdr rest))))) - ;; Now warn. - (if (cdr byte-compile-unresolved-functions) - (let* ((str "The following functions are not known to be defined: ") - (L (+ (length str) 5)) - (rest (reverse byte-compile-unresolved-functions)) - s) - (while rest - (setq s (symbol-name (car (car rest))) - L (+ L (length s) 2) - rest (cdr rest)) - (if (<= L (1- fill-column)) - (setq str (concat str " " s (and rest ","))) - (setq str (concat str "\n " s (and rest ",")) - L (+ (length s) 4)))) - (byte-compile-warn "%s" str)) - (if byte-compile-unresolved-functions - (byte-compile-warn "the function %s is not known to be defined." - (car (car byte-compile-unresolved-functions))))))) - nil) - -(defun byte-compile-defvar-p (var) - ;; Whether the byte compiler thinks that nonexical references to this - ;; variable are ok. - (or (globally-boundp var) - (let ((rest byte-compile-bound-variables)) - (while (and rest var) - (if (and (eq var (car-safe (car rest))) - (not (= 0 (logand (cdr (car rest)) - byte-compile-global-bit)))) - (setq var nil)) - (setq rest (cdr rest))) - ;; if var is nil at this point, it's a defvar in this file. - (not var)))) - - -;;; If we have compiled bindings of variables which have no referents, warn. -(defun byte-compile-warn-about-unused-variables () - (let ((rest byte-compile-bound-variables) - (unreferenced '()) - cell) - (while (and rest - ;; only warn about variables whose lifetime is now ending, - ;; that is, variables from the lexical scope that is now - ;; terminating. (Think nested lets.) - (not (eq (car rest) 'new-scope))) - (setq cell (car rest)) - (if (and (= 0 (logand byte-compile-referenced-bit (cdr cell))) - ;; Don't warn about declared-but-unused arguments, - ;; for two reasons: first, the arglist structure - ;; might be imposed by external forces, and we don't - ;; have (declare (ignore x)) yet; and second, inline - ;; expansion produces forms like - ;; ((lambda (arg) (byte-code "..." [arg])) x) - ;; which we can't (ok, well, don't) recognise as - ;; containing a reference to arg, so every inline - ;; expansion would generate a warning. (If we had - ;; `ignore' then inline expansion could emit an - ;; ignore declaration.) - (= 0 (logand byte-compile-arglist-bit (cdr cell))) - ;; Don't warn about defvars because this is a - ;; legitimate special binding. - (not (byte-compile-defvar-p (car cell)))) - (setq unreferenced (cons (car cell) unreferenced))) - (setq rest (cdr rest))) - (setq unreferenced (nreverse unreferenced)) - (while unreferenced - (byte-compile-warn - (format "variable %s bound but not referenced" (car unreferenced))) - (setq unreferenced (cdr unreferenced))))) - - -(defmacro byte-compile-constp (form) - ;; Returns non-nil if FORM is a constant. - (` (cond ((consp (, form)) (eq (car (, form)) 'quote)) - ((not (symbolp (, form)))) - ((keywordp (, form))) - ((memq (, form) '(nil t)))))) - -(defmacro byte-compile-close-variables (&rest body) - (cons 'let - (cons '(;; - ;; Close over these variables to encapsulate the - ;; compilation state - ;; - (byte-compile-macro-environment - ;; Copy it because the compiler may patch into the - ;; macroenvironment. - (copy-alist byte-compile-initial-macro-environment)) - (byte-compile-function-environment nil) - (byte-compile-autoload-environment nil) - (byte-compile-unresolved-functions nil) - (byte-compile-bound-variables nil) - (byte-compile-free-references nil) - (byte-compile-free-assignments nil) - ;; - ;; Close over these variables so that `byte-compiler-options' - ;; can change them on a per-file basis. - ;; - (byte-compile-verbose byte-compile-verbose) - (byte-optimize byte-optimize) - (byte-compile-emacs19-compatibility - byte-compile-emacs19-compatibility) - (byte-compile-dynamic byte-compile-dynamic) - (byte-compile-dynamic-docstrings - byte-compile-dynamic-docstrings) - (byte-compile-warnings (if (eq byte-compile-warnings t) - byte-compile-default-warnings - byte-compile-warnings)) - (byte-compile-file-domain nil) - ) - (list - (list 'prog1 (cons 'progn body) - '(if (memq 'unused-vars byte-compile-warnings) - ;; done compiling in this scope, warn now. - (byte-compile-warn-about-unused-variables))))))) - - -(defvar byte-compile-warnings-point-max nil) -(defmacro displaying-byte-compile-warnings (&rest body) - (list 'let - '((byte-compile-warnings-point-max byte-compile-warnings-point-max)) - ;; Log the file name. - '(byte-compile-log-file) - ;; Record how much is logged now. - ;; We will display the log buffer if anything more is logged - ;; before the end of BODY. - '(or byte-compile-warnings-point-max - (save-excursion - (set-buffer (get-buffer-create "*Compile-Log*")) - (setq byte-compile-warnings-point-max (point-max)))) - (list 'unwind-protect - (list 'condition-case 'error-info - (cons 'progn body) - '(error - (byte-compile-report-error error-info))) - '(save-excursion - ;; If there were compilation warnings, display them. - (set-buffer "*Compile-Log*") - (if (= byte-compile-warnings-point-max (point-max)) - nil - (select-window - (prog1 (selected-window) - (select-window (display-buffer (current-buffer))) - (goto-char byte-compile-warnings-point-max) - (recenter 1)))))))) - - -;;;###autoload -(defun byte-force-recompile (directory) - "Recompile every `.el' file in DIRECTORY that already has a `.elc' file. -Files in subdirectories of DIRECTORY are processed also." - (interactive "DByte force recompile (directory): ") - (byte-recompile-directory directory nil t)) - -;;;###autoload -(defun byte-recompile-directory (directory &optional arg norecursion force) - "Recompile every `.el' file in DIRECTORY that needs recompilation. -This is if a `.elc' file exists but is older than the `.el' file. -Files in subdirectories of DIRECTORY are processed also unless argument -NORECURSION is non-nil. - -If the `.elc' file does not exist, normally the `.el' file is *not* compiled. -But a prefix argument (optional second arg) means ask user, -for each such `.el' file, whether to compile it. Prefix argument 0 means -don't ask and compile the file anyway. - -A nonzero prefix argument also means ask about each subdirectory. - -If the fourth argument FORCE is non-nil, -recompile every `.el' file that already has a `.elc' file." - (interactive "DByte recompile directory: \nP") - (if arg - (setq arg (prefix-numeric-value arg))) - (if noninteractive - nil - (save-some-buffers) - (redraw-modeline)) - (let ((directories (list (expand-file-name directory))) - (file-count 0) - (dir-count 0) - last-dir) - (displaying-byte-compile-warnings - (while directories - (setq directory (file-name-as-directory (car directories))) - (or noninteractive (message "Checking %s..." directory)) - (let ((files (directory-files directory)) - source dest) - (while files - (setq source (expand-file-name (car files) directory)) - (if (and (not (member (car files) '("." ".." "RCS" "CVS" "SCCS"))) - ;; Stay away from directory back-links, etc: - (not (file-symlink-p source)) - (file-directory-p source) - byte-recompile-directory-recursively) - ;; This file is a subdirectory. Handle them differently. - (if (or (null arg) - (eq arg 0) - (y-or-n-p (concat "Check " source "? "))) - (setq directories - (nconc directories (list source)))) - ;; It is an ordinary file. Decide whether to compile it. - (if (and (string-match emacs-lisp-file-regexp source) - (not (auto-save-file-name-p source)) - (setq dest (byte-compile-dest-file source)) - (if (file-exists-p dest) - ;; File was already compiled. - (or force (file-newer-than-file-p source dest)) - ;; No compiled file exists yet. - (and arg - (or (eq 0 arg) - (y-or-n-p (concat "Compile " source "? ")))))) - (progn ;(if (and noninteractive (not byte-compile-verbose)) - ; (message "Compiling %s..." source)) - ; we do this in byte-compile-file. - (if byte-recompile-directory-ignore-errors-p - (batch-byte-compile-1 source) - (byte-compile-file source)) - (or noninteractive - (message "Checking %s..." directory)) - (setq file-count (1+ file-count)) - (if (not (eq last-dir directory)) - (setq last-dir directory - dir-count (1+ dir-count))) - ))) - (setq files (cdr files)))) - (setq directories (cdr directories)))) - (message "Done (Total of %d file%s compiled%s)" - file-count (if (= file-count 1) "" "s") - (if (> dir-count 1) (format " in %d directories" dir-count) "")))) - -;;;###autoload -(defun byte-recompile-file (filename &optional force) - "Recompile a file of Lisp code named FILENAME if it needs recompilation. -This is if the `.elc' file exists but is older than the `.el' file. - -If the `.elc' file does not exist, normally the `.el' file is *not* -compiled. But a prefix argument (optional second arg) means ask user -whether to compile it. Prefix argument 0 don't ask and recompile anyway." - (interactive "fByte recompile file: \nP") - (let ((dest)) - (if (and (string-match emacs-lisp-file-regexp filename) - (not (auto-save-file-name-p filename)) - (setq dest (byte-compile-dest-file filename)) - (if (file-exists-p dest) - (file-newer-than-file-p filename dest) - (and force - (or (eq 0 force) - (y-or-n-p (concat "Compile " filename "? ")))))) - (byte-compile-file filename)))) - -(defvar kanji-flag nil) - -;;;###autoload -(defun byte-compile-file (filename &optional load) - "Compile a file of Lisp code named FILENAME into a file of byte code. -The output file's name is made by appending `c' to the end of FILENAME. -With prefix arg (noninteractively: 2nd arg), load the file after compiling." -;; (interactive "fByte compile file: \nP") - (interactive - (let ((file buffer-file-name) - (file-name nil) - (file-dir nil)) - (and file - (eq (cdr (assq 'major-mode (buffer-local-variables))) - 'emacs-lisp-mode) - (setq file-name (file-name-nondirectory file) - file-dir (file-name-directory file))) - (list (read-file-name (if current-prefix-arg - "Byte compile and load file: " - "Byte compile file: ") - file-dir nil nil file-name) - current-prefix-arg))) - ;; Expand now so we get the current buffer's defaults - (setq filename (expand-file-name filename)) - - ;; If we're compiling a file that's in a buffer and is modified, offer - ;; to save it first. - (or noninteractive - (let ((b (get-file-buffer (expand-file-name filename)))) - (if (and b (buffer-modified-p b) - (y-or-n-p (format "save buffer %s first? " (buffer-name b)))) - (save-excursion (set-buffer b) (save-buffer))))) - - (if (or noninteractive byte-compile-verbose) ; XEmacs change - (message "Compiling %s..." filename)) - (let (;;(byte-compile-current-file (file-name-nondirectory filename)) - (byte-compile-current-file filename) - (debug-issue-ebola-notices 0) ; Hack -slb - target-file input-buffer output-buffer - byte-compile-dest-file) - (setq target-file (byte-compile-dest-file filename)) - (setq byte-compile-dest-file target-file) - (save-excursion - (setq input-buffer (get-buffer-create " *Compiler Input*")) - (set-buffer input-buffer) - (erase-buffer) - (insert-file-contents filename) - ;; Run hooks including the uncompression hook. - ;; If they change the file name, then change it for the output also. - (let ((buffer-file-name filename) - (default-major-mode 'emacs-lisp-mode) - (enable-local-eval nil)) - (normal-mode) - (setq filename buffer-file-name))) - (setq byte-compiler-error-flag nil) - ;; It is important that input-buffer not be current at this call, - ;; so that the value of point set in input-buffer - ;; within byte-compile-from-buffer lingers in that buffer. - (setq output-buffer (byte-compile-from-buffer input-buffer filename)) - (if byte-compiler-error-flag - nil - (if byte-compile-verbose - (message "Compiling %s...done" filename)) - (kill-buffer input-buffer) - (save-excursion - (set-buffer output-buffer) - (goto-char (point-max)) - (insert "\n") ; aaah, unix. - (let ((vms-stmlf-recfm t)) - (setq target-file (byte-compile-dest-file filename)) - (or byte-compile-overwrite-file - (condition-case () - (delete-file target-file) - (error nil))) - (if (file-writable-p target-file) - (let ((kanji-flag nil)) ; for nemacs, from Nakagawa Takayuki - (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt)) - (setq buffer-file-type t)) - (write-region 1 (point-max) target-file)) - ;; This is just to give a better error message than write-region - (signal 'file-error - (list "Opening output file" - (if (file-exists-p target-file) - "cannot overwrite file" - "directory not writable or nonexistent") - target-file))) - (or byte-compile-overwrite-file - (condition-case () - (set-file-modes target-file (file-modes filename)) - (error nil)))) - (kill-buffer (current-buffer))) - (if (and byte-compile-generate-call-tree - (or (eq t byte-compile-generate-call-tree) - (y-or-n-p (format "Report call tree for %s? " filename)))) - (save-excursion - (display-call-tree filename))) - (if load - (load target-file)) - t))) - -;; RMS comments the next two out. -(defun byte-compile-and-load-file (&optional filename) - "Compile a file of Lisp code named FILENAME into a file of byte code, -and then load it. The output file's name is made by appending \"c\" to -the end of FILENAME." - (interactive) - (if filename ; I don't get it, (interactive-p) doesn't always work - (byte-compile-file filename t) - (let ((current-prefix-arg '(4))) - (call-interactively 'byte-compile-file)))) - -(defun byte-compile-buffer (&optional buffer) - "Byte-compile and evaluate contents of BUFFER (default: the current buffer)." - (interactive "bByte compile buffer: ") - (setq buffer (if buffer (get-buffer buffer) (current-buffer))) - (message "Compiling %s..." (buffer-name buffer)) - (let* ((filename (or (buffer-file-name buffer) - (concat "#"))) - (byte-compile-current-file buffer)) - (byte-compile-from-buffer buffer filename t)) - (message "Compiling %s...done" (buffer-name buffer)) - t) - -;;; compiling a single function -;;;###autoload -(defun compile-defun (&optional arg) - "Compile and evaluate the current top-level form. -Print the result in the minibuffer. -With argument, insert value in current buffer after the form." - (interactive "P") - (save-excursion - (end-of-defun) - (beginning-of-defun) - (let* ((byte-compile-current-file (buffer-file-name)) - (load-file-name (buffer-file-name)) - (byte-compile-last-warned-form 'nothing) - (value (eval (displaying-byte-compile-warnings - (byte-compile-sexp (read (current-buffer)) - "toplevel forms"))))) - (cond (arg - (message "Compiling from buffer... done.") - (prin1 value (current-buffer)) - (insert "\n")) - ((message "%s" (prin1-to-string value))))))) - -(defvar byte-compile-inbuffer) -(defvar byte-compile-outbuffer) - -(defun byte-compile-from-buffer (byte-compile-inbuffer filename &optional eval) - ;; buffer --> output-buffer, or buffer --> eval form, return nil - (let (byte-compile-outbuffer - ;; Prevent truncation of flonums and lists as we read and print them - (float-output-format nil) - (case-fold-search nil) - (print-length nil) - (print-level nil) - ;; Simulate entry to byte-compile-top-level - (byte-compile-constants nil) - (byte-compile-variables nil) - (byte-compile-tag-number 0) - (byte-compile-depth 0) - (byte-compile-maxdepth 0) - (byte-compile-output nil) - ;; #### This is bound in b-c-close-variables. - ;; (byte-compile-warnings (if (eq byte-compile-warnings t) - ;; byte-compile-warning-types - ;; byte-compile-warnings)) - ) - (byte-compile-close-variables - (save-excursion - (setq byte-compile-outbuffer - (set-buffer (get-buffer-create " *Compiler Output*"))) - (erase-buffer) - ;; (emacs-lisp-mode) - (setq case-fold-search nil) - (and filename - (not eval) - (byte-compile-insert-header filename - byte-compile-inbuffer - byte-compile-outbuffer)) - - ;; This is a kludge. Some operating systems (OS/2, DOS) need to - ;; write files containing binary information specially. - ;; Under most circumstances, such files will be in binary - ;; overwrite mode, so those OS's use that flag to guess how - ;; they should write their data. Advise them that .elc files - ;; need to be written carefully. - (setq overwrite-mode 'overwrite-mode-binary)) - (displaying-byte-compile-warnings - (save-excursion - (set-buffer byte-compile-inbuffer) - (goto-char 1) - - ;; Compile the forms from the input buffer. - (while (progn - (while (progn (skip-chars-forward " \t\n\^l") - (looking-at ";")) - (forward-line 1)) - (not (eobp))) - (byte-compile-file-form (read byte-compile-inbuffer))) - - ;; Compile pending forms at end of file. - (byte-compile-flush-pending) - (byte-compile-warn-about-unresolved-functions) - ;; SHould we always do this? When calling multiple files, it - ;; would be useful to delay this warning until all have - ;; been compiled. - (setq byte-compile-unresolved-functions nil))) - (save-excursion - (set-buffer byte-compile-outbuffer) - (goto-char (point-min)))) - (if (not eval) - byte-compile-outbuffer - (let (form) - (while (condition-case nil - (progn (setq form (read byte-compile-outbuffer)) - t) - (end-of-file nil)) - (eval form))) - (kill-buffer byte-compile-outbuffer) - nil))) - -(defun byte-compile-insert-header (filename byte-compile-inbuffer - byte-compile-outbuffer) - (set-buffer byte-compile-inbuffer) - (let ((dynamic-docstrings byte-compile-dynamic-docstrings)) - (set-buffer byte-compile-outbuffer) - (goto-char 1) - ;; - ;; The magic number of .elc files is ";ELC", or 0x3B454C43. After that is - ;; the file-format version number (19 or 20) as a byte, followed by some - ;; nulls. The primary motivation for doing this is to get some binary - ;; characters up in the first line of the file so that `diff' will simply - ;; say "Binary files differ" instead of actually doing a diff of two .elc - ;; files. An extra benefit is that you can add this to /etc/magic: - ;; - ;; 0 string ;ELC GNU Emacs Lisp compiled file, - ;; >4 byte x version %d - ;; - (insert - ";ELC" - (if (byte-compile-version-cond byte-compile-emacs19-compatibility) 19 20) - "\000\000\000\n" - ) - (insert ";;; compiled by " - (or (and (boundp 'user-mail-address) user-mail-address) - (concat (user-login-name) "@" (system-name))) - " on " - (current-time-string) "\n;;; from file " filename "\n") - (insert ";;; emacs version " emacs-version ".\n") - (insert ";;; bytecomp version " byte-compile-version "\n;;; " - (cond - ((eq byte-optimize 'source) "source-level optimization only") - ((eq byte-optimize 'byte) "byte-level optimization only") - (byte-optimize "optimization is on") - (t "optimization is off")) - (if (byte-compile-version-cond byte-compile-emacs19-compatibility) - "; compiled with Emacs 19 compatibility.\n" - ".\n")) - (if (not (byte-compile-version-cond byte-compile-emacs19-compatibility)) - (insert ";;; this file uses opcodes which do not exist in Emacs 19.\n" - ;; Have to check if emacs-version is bound so that this works - ;; in files loaded early in loadup.el. - "\n(if (and (boundp 'emacs-version)\n" - "\t (or (and (boundp 'epoch::version) epoch::version)\n" - "\t (string-lessp emacs-version \"20\")))\n" - " (error \"`" - ;; prin1-to-string is used to quote backslashes. - (substring (prin1-to-string (file-name-nondirectory filename)) - 1 -1) - "' was compiled for Emacs 20\"))\n\n")) - (insert "(or (boundp 'current-load-list) (setq current-load-list nil))\n" - "\n") - (if (and (byte-compile-version-cond byte-compile-emacs19-compatibility) - dynamic-docstrings) - (insert ";;; this file uses opcodes which do not exist prior to\n" - ";;; XEmacs 19.14/GNU Emacs 19.29 or later." - ;; Have to check if emacs-version is bound so that this works - ;; in files loaded early in loadup.el. - "\n(if (and (boundp 'emacs-version)\n" - "\t (or (and (boundp 'epoch::version) epoch::version)\n" - "\t (and (not (string-match \"XEmacs\" emacs-version))\n" - "\t (string-lessp emacs-version \"19.29\"))\n" - "\t (string-lessp emacs-version \"19.14\")))\n" - " (error \"`" - ;; prin1-to-string is used to quote backslashes. - (substring (prin1-to-string (file-name-nondirectory filename)) - 1 -1) - "' was compiled for XEmacs 19.14/Emacs 19.29 or later\"))\n\n" - ) - )) - - ;; back in the inbuffer; determine and set the coding system for the .elc - ;; file if under Mule. If there are any extended characters in the - ;; input file, use `escape-quoted' to make sure that both binary and - ;; extended characters are output properly and distinguished properly. - ;; Otherwise, use `no-conversion' for maximum portability with non-Mule - ;; Emacsen. - (if (featurep 'mule) - (if (save-excursion - (set-buffer byte-compile-inbuffer) - (goto-char (point-min)) - ;; mrb- There must be a better way than skip-chars-forward - (skip-chars-forward (concat (char-to-string 0) "-" - (char-to-string 255))) - (eq (point) (point-max))) - (setq buffer-file-coding-system 'no-conversion) - (insert "(require 'mule)\n;;;###coding system: escape-quoted\n") - (setq buffer-file-coding-system 'escape-quoted) - ;; Lazy loading not yet implemented for MULE files - ;; mrb - Fix this someday. - (save-excursion - (set-buffer byte-compile-inbuffer) - (setq byte-compile-dynamic nil - byte-compile-dynamic-docstrings nil)) - ;;(external-debugging-output (prin1-to-string (buffer-local-variables)))) - )) - ) - - -(defun byte-compile-output-file-form (form) - ;; writes the given form to the output buffer, being careful of docstrings - ;; in defun, defmacro, defvar, defconst and autoload because make-docfile is - ;; so amazingly stupid. - ;; defalias calls are output directly by byte-compile-file-form-defmumble; - ;; it does not pay to first build the defalias in defmumble and then parse - ;; it here. - (if (and (memq (car-safe form) '(defun defmacro defvar defconst autoload)) - (stringp (nth 3 form))) - (byte-compile-output-docform nil nil '("\n(" 3 ")") form nil - (eq (car form) 'autoload)) - (let ((print-escape-newlines t) - (print-length nil) - (print-level nil) - (print-readably t) ; print #[] for bytecode, 'x for (quote x) - (print-gensym nil)) ; this is too dangerous for now - (princ "\n" byte-compile-outbuffer) - (prin1 form byte-compile-outbuffer) - nil))) - -(defun byte-compile-output-docform (preface name info form specindex quoted) - "Print a form with a doc string. INFO is (prefix doc-index postfix). -If PREFACE and NAME are non-nil, print them too, -before INFO and the FORM but after the doc string itself. -If SPECINDEX is non-nil, it is the index in FORM -of the function bytecode string. In that case, -we output that argument and the following argument (the constants vector) -together, for lazy loading. -QUOTED says that we have to put a quote before the -list that represents a doc string reference. -`autoload' needs that." - ;; We need to examine byte-compile-dynamic-docstrings - ;; in the input buffer (now current), not in the output buffer. - (let ((dynamic-docstrings byte-compile-dynamic-docstrings)) - (set-buffer - (prog1 (current-buffer) - (set-buffer byte-compile-outbuffer) - (let (position) - - ;; Insert the doc string, and make it a comment with #@LENGTH. - (and (>= (nth 1 info) 0) - dynamic-docstrings - (progn - ;; Make the doc string start at beginning of line - ;; for make-docfile's sake. - (insert "\n") - (setq position - (byte-compile-output-as-comment - (nth (nth 1 info) form) nil)) - ;; If the doc string starts with * (a user variable), - ;; negate POSITION. - (if (and (stringp (nth (nth 1 info) form)) - (> (length (nth (nth 1 info) form)) 0) - (char= (aref (nth (nth 1 info) form) 0) ?*)) - (setq position (- position))))) - - (if preface - (progn - (insert preface) - (prin1 name byte-compile-outbuffer))) - (insert (car info)) - (let ((print-escape-newlines t) - (print-readably t) ; print #[] for bytecode, 'x for (quote x) - (print-gensym nil) ; this is too dangerous for now - (index 0)) - (prin1 (car form) byte-compile-outbuffer) - (while (setq form (cdr form)) - (setq index (1+ index)) - (insert " ") - (cond ((and (numberp specindex) (= index specindex)) - (let ((position - (byte-compile-output-as-comment - (cons (car form) (nth 1 form)) - t))) - (princ (format "(#$ . %d) nil" position) - byte-compile-outbuffer) - (setq form (cdr form)) - (setq index (1+ index)))) - ((= index (nth 1 info)) - (if position - (princ (format (if quoted "'(#$ . %d)" "(#$ . %d)") - position) - byte-compile-outbuffer) - (let ((print-escape-newlines nil)) - (goto-char (prog1 (1+ (point)) - (prin1 (car form) - byte-compile-outbuffer))) - (insert "\\\n") - (goto-char (point-max))))) - (t - (prin1 (car form) byte-compile-outbuffer))))) - (insert (nth 2 info)))))) - nil) - -(defvar for-effect) ; ## Kludge! This should be an arg, not a special. - -(defun byte-compile-keep-pending (form &optional handler) - (if (memq byte-optimize '(t source)) - (setq form (byte-optimize-form form t))) - (if handler - (let ((for-effect t)) - ;; To avoid consing up monstrously large forms at load time, we split - ;; the output regularly. - (and (memq (car-safe form) '(fset defalias define-function)) - (nthcdr 300 byte-compile-output) - (byte-compile-flush-pending)) - (funcall handler form) - (if for-effect - (byte-compile-discard))) - (byte-compile-form form t)) - nil) - -(defun byte-compile-flush-pending () - (if byte-compile-output - (let ((form (byte-compile-out-toplevel t 'file))) - (cond ((eq (car-safe form) 'progn) - (mapcar 'byte-compile-output-file-form (cdr form))) - (form - (byte-compile-output-file-form form))) - (setq byte-compile-constants nil - byte-compile-variables nil - byte-compile-depth 0 - byte-compile-maxdepth 0 - byte-compile-output nil)))) - -(defun byte-compile-file-form (form) - (let ((byte-compile-current-form nil) ; close over this for warnings. - handler) - (cond - ((not (consp form)) - (byte-compile-keep-pending form)) - ((and (symbolp (car form)) - (setq handler (get (car form) 'byte-hunk-handler))) - (cond ((setq form (funcall handler form)) - (byte-compile-flush-pending) - (byte-compile-output-file-form form)))) - ((eq form (setq form (macroexpand form byte-compile-macro-environment))) - (byte-compile-keep-pending form)) - (t - (byte-compile-file-form form))))) - -;; Functions and variables with doc strings must be output separately, -;; so make-docfile can recognise them. Most other things can be output -;; as byte-code. - -(put 'defsubst 'byte-hunk-handler 'byte-compile-file-form-defsubst) -(defun byte-compile-file-form-defsubst (form) - (cond ((assq (nth 1 form) byte-compile-unresolved-functions) - (setq byte-compile-current-form (nth 1 form)) - (byte-compile-warn "defsubst %s was used before it was defined" - (nth 1 form)))) - (byte-compile-file-form - (macroexpand form byte-compile-macro-environment)) - ;; Return nil so the form is not output twice. - nil) - -(put 'autoload 'byte-hunk-handler 'byte-compile-file-form-autoload) -(defun byte-compile-file-form-autoload (form) - ;; - ;; If this is an autoload of a macro, and all arguments are constants (that - ;; is, there is no hairy computation going on here) then evaluate the form - ;; at compile-time. This is so that we can make use of macros which we - ;; have autoloaded from the file being compiled. Normal function autoloads - ;; are not automatically evaluated at compile time, because there's not - ;; much point to it (so why bother cluttering up the compile-time namespace.) - ;; - ;; If this is an autoload of a function, then record its definition in the - ;; byte-compile-autoload-environment to suppress any `not known to be - ;; defined' warnings at the end of this file (this only matters for - ;; functions which are autoloaded and compiled in the same file, if the - ;; autoload already exists in the compilation environment, we wouldn't have - ;; warned anyway.) - ;; - (let* ((name (if (byte-compile-constp (nth 1 form)) - (eval (nth 1 form)))) - ;; In v19, the 5th arg to autoload can be t, nil, 'macro, or 'keymap. - (macrop (and (byte-compile-constp (nth 5 form)) - (memq (eval (nth 5 form)) '(t macro)))) -;; (functionp (and (byte-compile-constp (nth 5 form)) -;; (eq 'nil (eval (nth 5 form))))) - ) - (if (and macrop - (let ((form form)) - ;; all forms are constant - (while (if (setq form (cdr form)) - (byte-compile-constp (car form)))) - (null form))) - ;; eval the macro autoload into the compilation enviroment - (eval form)) - - (if name - (let ((old (assq name byte-compile-autoload-environment))) - (cond (old - (if (memq 'redefine byte-compile-warnings) - (byte-compile-warn "multiple autoloads for %s" name)) - (setcdr old form)) - (t - ;; We only use the names in the autoload environment, but - ;; it might be useful to have the bodies some day. - (setq byte-compile-autoload-environment - (cons (cons name form) - byte-compile-autoload-environment))))))) - ;; - ;; Now output the form. - (if (stringp (nth 3 form)) - form - ;; No doc string, so we can compile this as a normal form. - (byte-compile-keep-pending form 'byte-compile-normal-call))) - -(put 'defvar 'byte-hunk-handler 'byte-compile-file-form-defvar) -(put 'defconst 'byte-hunk-handler 'byte-compile-file-form-defvar) -(defun byte-compile-file-form-defvar (form) - (if (> (length form) 4) - (byte-compile-warn "%s used with too many args (%s)" - (car form) (nth 1 form))) - (if (and (> (length form) 3) (not (stringp (nth 3 form)))) - (byte-compile-warn "Third arg to %s %s is not a string: %s" - (car form) (nth 1 form) (nth 3 form))) - (if (null (nth 3 form)) - ;; Since there is no doc string, we can compile this as a normal form, - ;; and not do a file-boundary. - (byte-compile-keep-pending form) - (if (memq 'free-vars byte-compile-warnings) - (setq byte-compile-bound-variables - (cons (cons (nth 1 form) byte-compile-global-bit) - byte-compile-bound-variables))) - (cond ((consp (nth 2 form)) - (setq form (copy-sequence form)) - (setcar (cdr (cdr form)) - (byte-compile-top-level (nth 2 form) nil 'file)))) - - ;; The following turns out not to be necessary, since we emit a call to - ;; defvar, which can hack Vfile_domain by itself! - ;; - ;; If a file domain has been set, emit (put 'VAR 'variable-domain ...) - ;; after this defvar. -; (if byte-compile-file-domain -; (progn -; ;; Actually, this will emit the (put ...) before the (defvar ...) -; ;; but I don't think that can matter in this case. -; (byte-compile-keep-pending -; (list 'put (list 'quote (nth 1 form)) ''variable-domain -; (list 'quote byte-compile-file-domain))))) - form)) - -(put 'require 'byte-hunk-handler 'byte-compile-file-form-eval-boundary) -(defun byte-compile-file-form-eval-boundary (form) - (eval form) - (byte-compile-keep-pending form 'byte-compile-normal-call)) - -(put 'progn 'byte-hunk-handler 'byte-compile-file-form-progn) -(put 'prog1 'byte-hunk-handler 'byte-compile-file-form-progn) -(put 'prog2 'byte-hunk-handler 'byte-compile-file-form-progn) -(defun byte-compile-file-form-progn (form) - (mapcar 'byte-compile-file-form (cdr form)) - ;; Return nil so the forms are not output twice. - nil) - -;; This handler is not necessary, but it makes the output from dont-compile -;; and similar macros cleaner. -(put 'eval 'byte-hunk-handler 'byte-compile-file-form-eval) -(defun byte-compile-file-form-eval (form) - (if (eq (car-safe (nth 1 form)) 'quote) - (nth 1 (nth 1 form)) - (byte-compile-keep-pending form))) - -(put 'defun 'byte-hunk-handler 'byte-compile-file-form-defun) -(defun byte-compile-file-form-defun (form) - (byte-compile-file-form-defmumble form nil)) - -(put 'defmacro 'byte-hunk-handler 'byte-compile-file-form-defmacro) -(defun byte-compile-file-form-defmacro (form) - (byte-compile-file-form-defmumble form t)) - -(defun byte-compile-compiled-obj-to-list (obj) - ;; #### this is fairly disgusting. Rewrite the code instead - ;; so that it doesn't create compiled objects in the first place! - ;; Much better than creating them and then "uncreating" them - ;; like this. - (read (concat "(" - (substring (let ((print-readably t)) - (prin1-to-string obj)) - 2 -1) - ")"))) - -(defun byte-compile-file-form-defmumble (form macrop) - (let* ((name (car (cdr form))) - (this-kind (if macrop 'byte-compile-macro-environment - 'byte-compile-function-environment)) - (that-kind (if macrop 'byte-compile-function-environment - 'byte-compile-macro-environment)) - (this-one (assq name (symbol-value this-kind))) - (that-one (assq name (symbol-value that-kind))) - (byte-compile-free-references nil) - (byte-compile-free-assignments nil)) - - ;; When a function or macro is defined, add it to the call tree so that - ;; we can tell when functions are not used. - (if byte-compile-generate-call-tree - (or (assq name byte-compile-call-tree) - (setq byte-compile-call-tree - (cons (list name nil nil) byte-compile-call-tree)))) - - (setq byte-compile-current-form name) ; for warnings - (if (memq 'redefine byte-compile-warnings) - (byte-compile-arglist-warn form macrop)) - (if byte-compile-verbose - (message "Compiling %s... (%s)" - ;; #### filename used free - (if filename (file-name-nondirectory filename) "") - (nth 1 form))) - (cond (that-one - (if (and (memq 'redefine byte-compile-warnings) - ;; hack hack: don't warn when compiling the stubs in - ;; bytecomp-runtime... - (not (assq (nth 1 form) - byte-compile-initial-macro-environment))) - (byte-compile-warn - "%s defined multiple times, as both function and macro" - (nth 1 form))) - (setcdr that-one nil)) - (this-one - (if (and (memq 'redefine byte-compile-warnings) - ;; hack: don't warn when compiling the magic internal - ;; byte-compiler macros in bytecomp-runtime.el... - (not (assq (nth 1 form) - byte-compile-initial-macro-environment))) - (byte-compile-warn "%s %s defined multiple times in this file" - (if macrop "macro" "function") - (nth 1 form)))) - ((and (fboundp name) - (or (subrp (symbol-function name)) - (eq (car-safe (symbol-function name)) - (if macrop 'lambda 'macro)))) - (if (memq 'redefine byte-compile-warnings) - (byte-compile-warn "%s %s being redefined as a %s" - (if (subrp (symbol-function name)) - "subr" - (if macrop "function" "macro")) - (nth 1 form) - (if macrop "macro" "function"))) - ;; shadow existing definition - (set this-kind - (cons (cons name nil) (symbol-value this-kind)))) - ) - (let ((body (nthcdr 3 form))) - (if (and (stringp (car body)) - (symbolp (car-safe (cdr-safe body))) - (car-safe (cdr-safe body)) - (stringp (car-safe (cdr-safe (cdr-safe body))))) - (byte-compile-warn "Probable `\"' without `\\' in doc string of %s" - (nth 1 form)))) - (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form)))) - (code (byte-compile-byte-code-maker new-one))) - (if this-one - (setcdr this-one new-one) - (set this-kind - (cons (cons name new-one) (symbol-value this-kind)))) - (if (and (stringp (nth 3 form)) - (eq 'quote (car-safe code)) - (eq 'lambda (car-safe (nth 1 code)))) - (cons (car form) - (cons name (cdr (nth 1 code)))) - (byte-compile-flush-pending) - (if (not (stringp (nth 3 form))) - ;; No doc string. Provide -1 as the "doc string index" - ;; so that no element will be treated as a doc string. - (byte-compile-output-docform - "\n(defalias '" - name - (cond ((atom code) - (if macrop '(" '(macro . #[" -1 "])") '(" #[" -1 "]"))) - ((eq (car code) 'quote) - (setq code new-one) - (if macrop '(" '(macro " -1 ")") '(" '(" -1 ")"))) - ((if macrop '(" (cons 'macro (" -1 "))") '(" (" -1 ")")))) - ;; FSF just calls `(append code nil)' here but that relies - ;; on horrible C kludges in concat() that accept byte- - ;; compiled objects and pretend they're vectors. - (if (compiled-function-p code) - (byte-compile-compiled-obj-to-list code) - (append code nil)) - (and (atom code) byte-compile-dynamic - 1) - nil) - ;; Output the form by hand, that's much simpler than having - ;; b-c-output-file-form analyze the defalias. - (byte-compile-output-docform - "\n(defalias '" - name - (cond ((atom code) ; compiled-function-p - (if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]"))) - ((eq (car code) 'quote) - (setq code new-one) - (if macrop '(" '(macro " 2 ")") '(" '(" 2 ")"))) - ((if macrop '(" (cons 'macro (" 5 "))") '(" (" 5 ")")))) - ;; The result of byte-compile-byte-code-maker is either a - ;; compiled-function object, or a list of some kind. If it's - ;; not a cons, we must coerce it into a list of the elements - ;; to be printed to the file. - (if (consp code) - code - (nconc (list - (compiled-function-arglist code) - (compiled-function-instructions code) - (compiled-function-constants code) - (compiled-function-stack-depth code)) - (let ((doc (documentation code t))) - (if doc (list doc))) - (if (commandp code) - (list (nth 1 (compiled-function-interactive code)))))) - (and (atom code) byte-compile-dynamic - 1) - nil)) - (princ ")" byte-compile-outbuffer) - nil)))) - -;; Print Lisp object EXP in the output file, inside a comment, -;; and return the file position it will have. -;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting. -(defun byte-compile-output-as-comment (exp quoted) - (let ((position (point))) - (set-buffer - (prog1 (current-buffer) - (set-buffer byte-compile-outbuffer) - - ;; Insert EXP, and make it a comment with #@LENGTH. - (insert " ") - (if quoted - (prin1 exp byte-compile-outbuffer) - (princ exp byte-compile-outbuffer)) - (goto-char position) - ;; Quote certain special characters as needed. - ;; get_doc_string in doc.c does the unquoting. - (while (search-forward "\^A" nil t) - (replace-match "\^A\^A" t t)) - (goto-char position) - (while (search-forward "\000" nil t) - (replace-match "\^A0" t t)) - (goto-char position) - (while (search-forward "\037" nil t) - (replace-match "\^A_" t t)) - (goto-char (point-max)) - (insert "\037") - (goto-char position) - (insert "#@" (format "%d" (- (point-max) position))) - - ;; Save the file position of the object. - ;; Note we should add 1 to skip the space - ;; that we inserted before the actual doc string, - ;; and subtract 1 to convert from an 1-origin Emacs position - ;; to a file position; they cancel. - (setq position (point)) - (goto-char (point-max)))) - position)) - - - -;; The `domain' declaration. This is legal only at top-level in a file, and -;; should generally be the first form in the file. It is not legal inside -;; function bodies. - -(put 'domain 'byte-hunk-handler 'byte-compile-file-form-domain) -(defun byte-compile-file-form-domain (form) - (if (not (null (cdr (cdr form)))) - (byte-compile-warn "domain used with too many arguments: %s" form)) - (let ((domain (nth 1 form))) - (or (null domain) - (stringp domain) - (progn - (byte-compile-warn - "argument to `domain' declaration must be a literal string: %s" - form) - (setq domain nil))) - (setq byte-compile-file-domain domain)) - (byte-compile-keep-pending form 'byte-compile-normal-call)) - -(defun byte-compile-domain (form) - (byte-compile-warn "The `domain' declaration is legal only at top-level: %s" - (let ((print-escape-newlines t) - (print-level 4) - (print-length 4)) - (prin1-to-string form))) - (byte-compile-normal-call - (list 'signal ''error - (list 'quote (list "`domain' used inside a function" form))))) - -;; This is part of bytecomp.el in 19.35: -(put 'custom-declare-variable 'byte-hunk-handler - 'byte-compile-file-form-custom-declare-variable) -(defun byte-compile-file-form-custom-declare-variable (form) - (if (memq 'free-vars byte-compile-warnings) - (setq byte-compile-bound-variables - (cons (cons (nth 1 (nth 1 form)) - byte-compile-global-bit) - byte-compile-bound-variables))) - form) - - -;;;###autoload -(defun byte-compile (form) - "If FORM is a symbol, byte-compile its function definition. -If FORM is a lambda or a macro, byte-compile it as a function." - (displaying-byte-compile-warnings - (byte-compile-close-variables - (let* ((fun (if (symbolp form) - (and (fboundp form) (symbol-function form)) - form)) - (macro (eq (car-safe fun) 'macro))) - (if macro - (setq fun (cdr fun))) - (cond ((eq (car-safe fun) 'lambda) - (setq fun (if macro - (cons 'macro (byte-compile-lambda fun)) - (byte-compile-lambda fun))) - (if (symbolp form) - (defalias form fun) - fun))))))) - -;;;###autoload -(defun byte-compile-sexp (sexp &optional msg) - "Compile and return SEXP." - (displaying-byte-compile-warnings - (byte-compile-close-variables - (prog1 - (byte-compile-top-level sexp) - (byte-compile-warn-about-unresolved-functions msg))))) - -;; Given a function made by byte-compile-lambda, make a form which produces it. -(defun byte-compile-byte-code-maker (fun) - (cond - ;; ## atom is faster than compiled-func-p. - ((atom fun) ; compiled-function-p - fun) - ;; b-c-lambda didn't produce a compiled-function, so it must be a trivial - ;; function. - ((let (tmp) - (if (and (setq tmp (assq 'byte-code (cdr-safe (cdr fun)))) - (null (cdr (memq tmp fun)))) - ;; Generate a make-byte-code call. - (let* ((interactive (assq 'interactive (cdr (cdr fun))))) - (nconc (list 'make-byte-code - (list 'quote (nth 1 fun)) ;arglist - (nth 1 tmp) ;bytes - (nth 2 tmp) ;consts - (nth 3 tmp)) ;depth - (cond ((stringp (nth 2 fun)) - (list (nth 2 fun))) ;doc - (interactive - (list nil))) - (cond (interactive - (list (if (or (null (nth 1 interactive)) - (stringp (nth 1 interactive))) - (nth 1 interactive) - ;; Interactive spec is a list or a variable - ;; (if it is correct). - (list 'quote (nth 1 interactive)))))))) - ;; a non-compiled function (probably trivial) - (list 'quote fun)))))) - -;; Byte-compile a lambda-expression and return a valid function. -;; The value is usually a compiled function but may be the original -;; lambda-expression. -(defun byte-compile-lambda (fun) - (or (eq 'lambda (car-safe fun)) - (error "not a lambda -- %s" (prin1-to-string fun))) - (let* ((arglist (nth 1 fun)) - (byte-compile-bound-variables - (let ((new-bindings - (mapcar (function (lambda (x) - (cons x byte-compile-arglist-bit))) - (and (memq 'free-vars byte-compile-warnings) - (delq '&rest (delq '&optional - (copy-sequence arglist))))))) - (nconc new-bindings - (cons 'new-scope byte-compile-bound-variables)))) - (body (cdr (cdr fun))) - (doc (if (stringp (car body)) - (prog1 (car body) - (setq body (cdr body))))) - (int (assq 'interactive body))) - (let ((rest arglist)) - (while rest - (cond ((not (symbolp (car rest))) - (byte-compile-warn "non-symbol in arglist: %s" - (prin1-to-string (car rest)))) - ((memq (car rest) '(t nil)) - (byte-compile-warn "constant in arglist: %s" (car rest))) - ((and (char= ?\& (aref (symbol-name (car rest)) 0)) - (not (memq (car rest) '(&optional &rest)))) - (byte-compile-warn "unrecognised `&' keyword in arglist: %s" - (car rest)))) - (setq rest (cdr rest)))) - (cond (int - ;; Skip (interactive) if it is in front (the most usual location). - (if (eq int (car body)) - (setq body (cdr body))) - (cond ((consp (cdr int)) - (if (cdr (cdr int)) - (byte-compile-warn "malformed interactive spec: %s" - (prin1-to-string int))) - ;; If the interactive spec is a call to `list', - ;; don't compile it, because `call-interactively' - ;; looks at the args of `list'. - (let ((form (nth 1 int))) - (while (or (eq (car-safe form) 'let) - (eq (car-safe form) 'let*) - (eq (car-safe form) 'save-excursion)) - (while (consp (cdr form)) - (setq form (cdr form))) - (setq form (car form))) - (or (eq (car-safe form) 'list) - (setq int (list 'interactive - (byte-compile-top-level (nth 1 int))))))) - ((cdr int) - (byte-compile-warn "malformed interactive spec: %s" - (prin1-to-string int)))))) - (let ((compiled (byte-compile-top-level (cons 'progn body) nil 'lambda))) - (if (memq 'unused-vars byte-compile-warnings) - ;; done compiling in this scope, warn now. - (byte-compile-warn-about-unused-variables)) - (if (eq 'byte-code (car-safe compiled)) - (apply 'make-byte-code - (append (list arglist) - ;; byte-string, constants-vector, stack depth - (cdr compiled) - ;; optionally, the doc string. - (if (or doc int) - (list doc)) - ;; optionally, the interactive spec. - (if int - (list (nth 1 int))))) - (setq compiled - (nconc (if int (list int)) - (cond ((eq (car-safe compiled) 'progn) (cdr compiled)) - (compiled (list compiled))))) - (nconc (list 'lambda arglist) - (if (or doc (stringp (car compiled))) - (cons doc (cond (compiled) - (body (list nil)))) - compiled)))))) - -(defun byte-compile-constants-vector () - ;; Builds the constants-vector from the current variables and constants. - ;; This modifies the constants from (const . nil) to (const . offset). - ;; To keep the byte-codes to look up the vector as short as possible: - ;; First 6 elements are vars, as there are one-byte varref codes for those. - ;; Next up to byte-constant-limit are constants, still with one-byte codes. - ;; Next variables again, to get 2-byte codes for variable lookup. - ;; The rest of the constants and variables need 3-byte byte-codes. - (let* ((i -1) - (rest (nreverse byte-compile-variables)) ; nreverse because the first - (other (nreverse byte-compile-constants)) ; vars often are used most. - ret tmp - (limits '(5 ; Use the 1-byte varref codes, - 63 ; 1-constlim ; 1-byte byte-constant codes, - 255 ; 2-byte varref codes, - 65535)) ; 3-byte codes for the rest. - limit) - (while (or rest other) - (setq limit (car limits)) - (while (and rest (not (eq i limit))) - (if (setq tmp (assq (car (car rest)) ret)) - (setcdr (car rest) (cdr tmp)) - (setcdr (car rest) (setq i (1+ i))) - (setq ret (cons (car rest) ret))) - (setq rest (cdr rest))) - (setq limits (cdr limits) - rest (prog1 other - (setq other rest)))) - (apply 'vector (nreverse (mapcar 'car ret))))) - -;; Given an expression FORM, compile it and return an equivalent byte-code -;; expression (a call to the function byte-code). -(defun byte-compile-top-level (form &optional for-effect output-type) - ;; OUTPUT-TYPE advises about how form is expected to be used: - ;; 'eval or nil -> a single form, - ;; 'progn or t -> a list of forms, - ;; 'lambda -> body of a lambda, - ;; 'file -> used at file-level. - (let ((byte-compile-constants nil) - (byte-compile-variables nil) - (byte-compile-tag-number 0) - (byte-compile-depth 0) - (byte-compile-maxdepth 0) - (byte-compile-output nil)) - (if (memq byte-optimize '(t source)) - (setq form (byte-optimize-form form for-effect))) - (while (and (eq (car-safe form) 'progn) (null (cdr (cdr form)))) - (setq form (nth 1 form))) - (if (and (eq 'byte-code (car-safe form)) - (not (memq byte-optimize '(t byte))) - (stringp (nth 1 form)) - (vectorp (nth 2 form)) - (natnump (nth 3 form))) - form - (byte-compile-form form for-effect) - (byte-compile-out-toplevel for-effect output-type)))) - -(defun byte-compile-out-toplevel (&optional for-effect output-type) - (if for-effect - ;; The stack is empty. Push a value to be returned from (byte-code ..). - (if (eq (car (car byte-compile-output)) 'byte-discard) - (setq byte-compile-output (cdr byte-compile-output)) - (byte-compile-push-constant - ;; Push any constant - preferably one which already is used, and - ;; a number or symbol - ie not some big sequence. The return value - ;; isn't returned, but it would be a shame if some textually large - ;; constant was not optimized away because we chose to return it. - (and (not (assq nil byte-compile-constants)) ; Nil is often there. - (let ((tmp (reverse byte-compile-constants))) - (while (and tmp (not (or (symbolp (car (car tmp))) - (numberp (car (car tmp)))))) - (setq tmp (cdr tmp))) - (car (car tmp))))))) - (byte-compile-out 'byte-return 0) - (setq byte-compile-output (nreverse byte-compile-output)) - (if (memq byte-optimize '(t byte)) - (setq byte-compile-output - (byte-optimize-lapcode byte-compile-output for-effect))) - - ;; Decompile trivial functions: - ;; only constants and variables, or a single funcall except in lambdas. - ;; Except for Lisp_Compiled objects, forms like (foo "hi") - ;; are still quicker than (byte-code "..." [foo "hi"] 2). - ;; Note that even (quote foo) must be parsed just as any subr by the - ;; interpreter, so quote should be compiled into byte-code in some contexts. - ;; What to leave uncompiled: - ;; lambda -> never. we used to leave it uncompiled if the body was - ;; a single atom, but that causes confusion if the docstring - ;; uses the (file . pos) syntax. Besides, now that we have - ;; the Lisp_Compiled type, the compiled form is faster. - ;; eval -> atom, quote or (function atom atom atom) - ;; progn -> as <> or (progn <> atom) - ;; file -> as progn, but takes both quotes and atoms, and longer forms. - (let (rest - (maycall (not (eq output-type 'lambda))) ; t if we may make a funcall. - tmp body) - (cond - ;; #### This should be split out into byte-compile-nontrivial-function-p. - ((or (eq output-type 'lambda) - (nthcdr (if (eq output-type 'file) 50 8) byte-compile-output) - (assq 'TAG byte-compile-output) ; Not necessary, but speeds up a bit. - (not (setq tmp (assq 'byte-return byte-compile-output))) - (progn - (setq rest (nreverse - (cdr (memq tmp (reverse byte-compile-output))))) - (while (cond - ((memq (car (car rest)) '(byte-varref byte-constant)) - (setq tmp (car (cdr (car rest)))) - (if (if (eq (car (car rest)) 'byte-constant) - (or (consp tmp) - (and (symbolp tmp) - (not (keywordp tmp)) - (not (memq tmp '(nil t)))))) - (if maycall - (setq body (cons (list 'quote tmp) body))) - (setq body (cons tmp body)))) - ((and maycall - ;; Allow a funcall if at most one atom follows it. - (null (nthcdr 3 rest)) - (setq tmp - ;; XEmacs change for rms funs - (or (and - (byte-compile-version-cond - byte-compile-emacs19-compatibility) - (get (car (car rest)) - 'byte-opcode19-invert)) - (get (car (car rest)) - 'byte-opcode-invert))) - (or (null (cdr rest)) - (and (memq output-type '(file progn t)) - (cdr (cdr rest)) - (eq (car (nth 1 rest)) 'byte-discard) - (progn (setq rest (cdr rest)) t)))) - (setq maycall nil) ; Only allow one real function call. - (setq body (nreverse body)) - (setq body (list - (if (and (eq tmp 'funcall) - (eq (car-safe (car body)) 'quote)) - (cons (nth 1 (car body)) (cdr body)) - (cons tmp body)))) - (or (eq output-type 'file) - (not (delq nil (mapcar 'consp (cdr (car body)))))))) - (setq rest (cdr rest))) - rest)) - (let ((byte-compile-vector (byte-compile-constants-vector))) - (list 'byte-code (byte-compile-lapcode byte-compile-output) - byte-compile-vector byte-compile-maxdepth))) - ;; it's a trivial function - ((cdr body) (cons 'progn (nreverse body))) - ((car body))))) - -;; Given BODY, compile it and return a new body. -(defun byte-compile-top-level-body (body &optional for-effect) - (setq body (byte-compile-top-level (cons 'progn body) for-effect t)) - (cond ((eq (car-safe body) 'progn) - (cdr body)) - (body - (list body)))) - -;; This is the recursive entry point for compiling each subform of an -;; expression. -;; If for-effect is non-nil, byte-compile-form will output a byte-discard -;; before terminating (ie no value will be left on the stack). -;; A byte-compile handler may, when for-effect is non-nil, choose output code -;; which does not leave a value on the stack, and then set for-effect to nil -;; (to prevent byte-compile-form from outputting the byte-discard). -;; If a handler wants to call another handler, it should do so via -;; byte-compile-form, or take extreme care to handle for-effect correctly. -;; (Use byte-compile-form-do-effect to reset the for-effect flag too.) -;; -(defun byte-compile-form (form &optional for-effect) - (setq form (macroexpand form byte-compile-macro-environment)) - (cond ((not (consp form)) - ;; XEmacs addition: keywordp - (cond ((or (not (symbolp form)) (keywordp form) (memq form '(nil t))) - (byte-compile-constant form)) - ((and for-effect byte-compile-delete-errors) - (setq for-effect nil)) - (t (byte-compile-variable-ref 'byte-varref form)))) - ((symbolp (car form)) - (let* ((fn (car form)) - (handler (get fn 'byte-compile))) - (if (memq fn '(t nil)) - (byte-compile-warn "%s called as a function" fn)) - (if (and handler - (or (not (byte-compile-version-cond - byte-compile-emacs19-compatibility)) - (not (get (get fn 'byte-opcode) 'emacs20-opcode)))) - (funcall handler form) - (if (memq 'callargs byte-compile-warnings) - (byte-compile-callargs-warn form)) - (byte-compile-normal-call form)))) - ((and (or (compiled-function-p (car form)) - (eq (car-safe (car form)) 'lambda)) - ;; if the form comes out the same way it went in, that's - ;; because it was malformed, and we couldn't unfold it. - (not (eq form (setq form (byte-compile-unfold-lambda form))))) - (byte-compile-form form for-effect) - (setq for-effect nil)) - ((byte-compile-normal-call form))) - (if for-effect - (byte-compile-discard))) - -(defun byte-compile-normal-call (form) - (if byte-compile-generate-call-tree - (byte-compile-annotate-call-tree form)) - (byte-compile-push-constant (car form)) - (mapcar 'byte-compile-form (cdr form)) ; wasteful, but faster. - (byte-compile-out 'byte-call (length (cdr form)))) - -;; kludge added to XEmacs to work around the bogosities of a nonlexical lisp. -(or (fboundp 'globally-boundp) (fset 'globally-boundp 'boundp)) - -(defun byte-compile-variable-ref (base-op var &optional varbind-flags) - (if (or (not (symbolp var)) (keywordp var) (memq var '(nil t))) - (byte-compile-warn (if (eq base-op 'byte-varbind) - "Attempt to let-bind %s %s" - "Variable reference to %s %s") - (if (symbolp var) "constant" "nonvariable") - (prin1-to-string var)) - (if (and (get var 'byte-obsolete-variable) - (memq 'obsolete byte-compile-warnings)) - (let ((ob (get var 'byte-obsolete-variable))) - (byte-compile-warn "%s is an obsolete variable; %s" var - (if (stringp ob) - ob - (format "use %s instead." ob))))) - (if (and (get var 'byte-compatible-variable) - (memq 'pedantic byte-compile-warnings)) - (let ((ob (get var 'byte-compatible-variable))) - (byte-compile-warn "%s is provided for compatibility; %s" var - (if (stringp ob) - ob - (format "use %s instead." ob))))) - (if (memq 'free-vars byte-compile-warnings) - (if (eq base-op 'byte-varbind) - (setq byte-compile-bound-variables - (cons (cons var (or varbind-flags 0)) - byte-compile-bound-variables)) - (or (globally-boundp var) - (let ((cell (assq var byte-compile-bound-variables))) - (if cell (setcdr cell - (logior (cdr cell) - (if (eq base-op 'byte-varset) - byte-compile-assigned-bit - byte-compile-referenced-bit))))) - (if (eq base-op 'byte-varset) - (or (memq var byte-compile-free-assignments) - (progn - (byte-compile-warn "assignment to free variable %s" - var) - (setq byte-compile-free-assignments - (cons var byte-compile-free-assignments)))) - (or (memq var byte-compile-free-references) - (progn - (byte-compile-warn "reference to free variable %s" var) - (setq byte-compile-free-references - (cons var byte-compile-free-references))))))))) - (let ((tmp (assq var byte-compile-variables))) - (or tmp - (setq tmp (list var) - byte-compile-variables (cons tmp byte-compile-variables))) - (byte-compile-out base-op tmp))) - -(defmacro byte-compile-get-constant (const) - (` (or (if (stringp (, const)) - (assoc (, const) byte-compile-constants) - (assq (, const) byte-compile-constants)) - (car (setq byte-compile-constants - (cons (list (, const)) byte-compile-constants)))))) - -;; Use this when the value of a form is a constant. This obeys for-effect. -(defun byte-compile-constant (const) - (if for-effect - (setq for-effect nil) - (byte-compile-out 'byte-constant (byte-compile-get-constant const)))) - -;; Use this for a constant that is not the value of its containing form. -;; This ignores for-effect. -(defun byte-compile-push-constant (const) - (let ((for-effect nil)) - (inline (byte-compile-constant const)))) - - -;; Compile those primitive ordinary functions -;; which have special byte codes just for speed. - -(defmacro byte-defop-compiler (function &optional compile-handler) - ;; add a compiler-form for FUNCTION. - ;; If function is a symbol, then the variable "byte-SYMBOL" must name - ;; the opcode to be used. If function is a list, the first element - ;; is the function and the second element is the bytecode-symbol. - ;; COMPILE-HANDLER is the function to use to compile this byte-op, or - ;; may be the abbreviations 0, 1, 2, 3, 0-1, 1-2, 2-3, 0+1, 1+1, 2+1, - ;; 0-1+1, 1-2+1, 2-3+1, 0+2, or 1+2. If it is nil, then the handler is - ;; "byte-compile-SYMBOL." - (let (opcode) - (if (symbolp function) - (setq opcode (intern (concat "byte-" (symbol-name function)))) - (setq opcode (car (cdr function)) - function (car function))) - (let ((fnform - (list 'put (list 'quote function) ''byte-compile - (list 'quote - (or (cdr (assq compile-handler - '((0 . byte-compile-no-args) - (1 . byte-compile-one-arg) - (2 . byte-compile-two-args) - (3 . byte-compile-three-args) - (0-1 . byte-compile-zero-or-one-arg) - (1-2 . byte-compile-one-or-two-args) - (2-3 . byte-compile-two-or-three-args) - (0+1 . byte-compile-no-args-with-one-extra) - (1+1 . byte-compile-one-arg-with-one-extra) - (2+1 . byte-compile-two-args-with-one-extra) - (0-1+1 . byte-compile-zero-or-one-arg-with-one-extra) - (1-2+1 . byte-compile-one-or-two-args-with-one-extra) - (2-3+1 . byte-compile-two-or-three-args-with-one-extra) - (0+2 . byte-compile-no-args-with-two-extra) - (1+2 . byte-compile-one-arg-with-two-extra) - - ))) - compile-handler - (intern (concat "byte-compile-" - (symbol-name function)))))))) - (if opcode - (list 'progn fnform - (list 'put (list 'quote function) - ''byte-opcode (list 'quote opcode)) - (list 'put (list 'quote opcode) - ''byte-opcode-invert (list 'quote function))) - fnform)))) - -(defmacro byte-defop-compiler20 (function &optional compile-handler) - ;; Just like byte-defop-compiler, but defines an opcode that will only - ;; be used when byte-compile-emacs19-compatibility is false. - (if (and (byte-compile-single-version) - byte-compile-emacs19-compatibility) - ;; #### instead of doing nothing, this should do some remprops, - ;; #### to protect against the case where a single-version compiler - ;; #### is loaded into a world that has contained a multi-version one. - nil - (list 'progn - (list 'put - (list 'quote - (or (car (cdr-safe function)) - (intern (concat "byte-" - (symbol-name (or (car-safe function) function)))))) - ''emacs20-opcode t) - (list 'byte-defop-compiler function compile-handler)))) - -;; XEmacs addition: -(defmacro byte-defop-compiler-rmsfun (function &optional compile-handler) - ;; for functions like `eq' that compile into different opcodes depending - ;; on the Emacs version: byte-old-eq for v19, byte-eq for v20. - (let ((opcode (intern (concat "byte-" (symbol-name function)))) - (opcode19 (intern (concat "byte-old-" (symbol-name function)))) - (fnform - (list 'put (list 'quote function) ''byte-compile - (list 'quote - (or (cdr (assq compile-handler - '((2 . byte-compile-two-args-19->20) - ))) - compile-handler - (intern (concat "byte-compile-" - (symbol-name function)))))))) - (list 'progn fnform - (list 'put (list 'quote function) - ''byte-opcode (list 'quote opcode)) - (list 'put (list 'quote function) - ''byte-opcode19 (list 'quote opcode19)) - (list 'put (list 'quote opcode) - ''byte-opcode-invert (list 'quote function)) - (list 'put (list 'quote opcode19) - ''byte-opcode19-invert (list 'quote function))))) - -(defmacro byte-defop-compiler-1 (function &optional compile-handler) - (list 'byte-defop-compiler (list function nil) compile-handler)) - - -(put 'byte-call 'byte-opcode-invert 'funcall) -(put 'byte-list1 'byte-opcode-invert 'list) -(put 'byte-list2 'byte-opcode-invert 'list) -(put 'byte-list3 'byte-opcode-invert 'list) -(put 'byte-list4 'byte-opcode-invert 'list) -(put 'byte-listN 'byte-opcode-invert 'list) -(put 'byte-concat2 'byte-opcode-invert 'concat) -(put 'byte-concat3 'byte-opcode-invert 'concat) -(put 'byte-concat4 'byte-opcode-invert 'concat) -(put 'byte-concatN 'byte-opcode-invert 'concat) -(put 'byte-insertN 'byte-opcode-invert 'insert) - -(byte-defop-compiler (dot byte-point) 0+1) -(byte-defop-compiler (dot-max byte-point-max) 0+1) -(byte-defop-compiler (dot-min byte-point-min) 0+1) -(byte-defop-compiler point 0+1) -(byte-defop-compiler-rmsfun eq 2) -(byte-defop-compiler point-max 0+1) -(byte-defop-compiler point-min 0+1) -(byte-defop-compiler following-char 0+1) -(byte-defop-compiler preceding-char 0+1) -(byte-defop-compiler current-column 0+1) -;; FSF has special function here; generalized here by the 1+2 stuff. -(byte-defop-compiler (indent-to-column byte-indent-to) 1+2) -(byte-defop-compiler indent-to 1+2) -(byte-defop-compiler-rmsfun equal 2) -(byte-defop-compiler eolp 0+1) -(byte-defop-compiler eobp 0+1) -(byte-defop-compiler bolp 0+1) -(byte-defop-compiler bobp 0+1) -(byte-defop-compiler current-buffer 0) -;;(byte-defop-compiler read-char 0) ;; obsolete -(byte-defop-compiler-rmsfun memq 2) -(byte-defop-compiler interactive-p 0) -(byte-defop-compiler widen 0+1) -(byte-defop-compiler end-of-line 0-1+1) -(byte-defop-compiler forward-char 0-1+1) -(byte-defop-compiler forward-line 0-1+1) -(byte-defop-compiler symbolp 1) -(byte-defop-compiler consp 1) -(byte-defop-compiler stringp 1) -(byte-defop-compiler listp 1) -(byte-defop-compiler not 1) -(byte-defop-compiler (null byte-not) 1) -(byte-defop-compiler car 1) -(byte-defop-compiler cdr 1) -(byte-defop-compiler length 1) -(byte-defop-compiler symbol-value 1) -(byte-defop-compiler symbol-function 1) -(byte-defop-compiler (1+ byte-add1) 1) -(byte-defop-compiler (1- byte-sub1) 1) -(byte-defop-compiler goto-char 1+1) -(byte-defop-compiler char-after 0-1+1) -(byte-defop-compiler set-buffer 1) -;;(byte-defop-compiler set-mark 1) ;; obsolete -(byte-defop-compiler forward-word 1+1) -(byte-defop-compiler char-syntax 1+1) -(byte-defop-compiler nreverse 1) -(byte-defop-compiler car-safe 1) -(byte-defop-compiler cdr-safe 1) -(byte-defop-compiler numberp 1) -(byte-defop-compiler integerp 1) -(byte-defop-compiler skip-chars-forward 1-2+1) -(byte-defop-compiler skip-chars-backward 1-2+1) -(byte-defop-compiler (eql byte-eq) 2) -(byte-defop-compiler20 old-eq 2) -(byte-defop-compiler20 old-memq 2) -(byte-defop-compiler cons 2) -(byte-defop-compiler aref 2) -(byte-defop-compiler (= byte-eqlsign) 2) -(byte-defop-compiler (< byte-lss) 2) -(byte-defop-compiler (> byte-gtr) 2) -(byte-defop-compiler (<= byte-leq) 2) -(byte-defop-compiler (>= byte-geq) 2) -(byte-defop-compiler get 2+1) -(byte-defop-compiler nth 2) -(byte-defop-compiler substring 2-3) -(byte-defop-compiler (move-marker byte-set-marker) 2-3) -(byte-defop-compiler set-marker 2-3) -(byte-defop-compiler match-beginning 1) -(byte-defop-compiler match-end 1) -(byte-defop-compiler upcase 1+1) -(byte-defop-compiler downcase 1+1) -(byte-defop-compiler string= 2) -(byte-defop-compiler string< 2) -(byte-defop-compiler (string-equal byte-string=) 2) -(byte-defop-compiler (string-lessp byte-string<) 2) -(byte-defop-compiler20 old-equal 2) -(byte-defop-compiler nthcdr 2) -(byte-defop-compiler elt 2) -(byte-defop-compiler20 old-member 2) -(byte-defop-compiler20 old-assq 2) -(byte-defop-compiler (rplaca byte-setcar) 2) -(byte-defop-compiler (rplacd byte-setcdr) 2) -(byte-defop-compiler setcar 2) -(byte-defop-compiler setcdr 2) -;; buffer-substring now has its own function. This used to be -;; 2+1, but now all args are optional. -(byte-defop-compiler buffer-substring) -(byte-defop-compiler delete-region 2+1) -(byte-defop-compiler narrow-to-region 2+1) -(byte-defop-compiler (% byte-rem) 2) -(byte-defop-compiler aset 3) - -(byte-defop-compiler-rmsfun member 2) -(byte-defop-compiler-rmsfun assq 2) - -(byte-defop-compiler max byte-compile-associative) -(byte-defop-compiler min byte-compile-associative) -(byte-defop-compiler (+ byte-plus) byte-compile-associative) -(byte-defop-compiler (* byte-mult) byte-compile-associative) - -;;####(byte-defop-compiler move-to-column 1) -(byte-defop-compiler-1 interactive byte-compile-noop) -(byte-defop-compiler-1 domain byte-compile-domain) - -;; As of GNU Emacs 19.18 and Lucid Emacs 19.8, mod and % are different: `%' -;; means integral remainder and may have a negative result; `mod' is always -;; positive, and accepts floating point args. All code which uses `mod' and -;; requires the new interpretation must be compiled with bytecomp version 2.18 -;; or newer, or the emitted code will run the byte-code for `%' instead of an -;; actual call to `mod'. So be careful of compiling new code with an old -;; compiler. Note also that `%' is more efficient than `mod' because the -;; former is byte-coded and the latter is not. -;;(byte-defop-compiler (mod byte-rem) 2) - - -(defun byte-compile-subr-wrong-args (form n) - (byte-compile-warn "%s called with %d arg%s, but requires %s" - (car form) (length (cdr form)) - (if (= 1 (length (cdr form))) "" "s") n) - ;; get run-time wrong-number-of-args error. - (byte-compile-normal-call form)) - -(defun byte-compile-no-args (form) - (if (not (= (length form) 1)) - (byte-compile-subr-wrong-args form "none") - (byte-compile-out (get (car form) 'byte-opcode) 0))) - -(defun byte-compile-one-arg (form) - (if (not (= (length form) 2)) - (byte-compile-subr-wrong-args form 1) - (byte-compile-form (car (cdr form))) ;; Push the argument - (byte-compile-out (get (car form) 'byte-opcode) 0))) - -(defun byte-compile-two-args (form) - (if (not (= (length form) 3)) - (byte-compile-subr-wrong-args form 2) - (byte-compile-form (car (cdr form))) ;; Push the arguments - (byte-compile-form (nth 2 form)) - (byte-compile-out (get (car form) 'byte-opcode) 0))) - -(defun byte-compile-three-args (form) - (if (not (= (length form) 4)) - (byte-compile-subr-wrong-args form 3) - (byte-compile-form (car (cdr form))) ;; Push the arguments - (byte-compile-form (nth 2 form)) - (byte-compile-form (nth 3 form)) - (byte-compile-out (get (car form) 'byte-opcode) 0))) - -(defun byte-compile-zero-or-one-arg (form) - (let ((len (length form))) - (cond ((= len 1) (byte-compile-one-arg (append form '(nil)))) - ((= len 2) (byte-compile-one-arg form)) - (t (byte-compile-subr-wrong-args form "0-1"))))) - -(defun byte-compile-one-or-two-args (form) - (let ((len (length form))) - (cond ((= len 2) (byte-compile-two-args (append form '(nil)))) - ((= len 3) (byte-compile-two-args form)) - (t (byte-compile-subr-wrong-args form "1-2"))))) - -(defun byte-compile-two-or-three-args (form) - (let ((len (length form))) - (cond ((= len 3) (byte-compile-three-args (append form '(nil)))) - ((= len 4) (byte-compile-three-args form)) - (t (byte-compile-subr-wrong-args form "2-3"))))) - -;; from Ben Wing : some inlined functions have extra -;; optional args added to them in XEmacs 19.12. Changing the byte -;; interpreter to deal with these args would be wrong and cause -;; incompatibility, so we generate non-inlined calls for those cases. -;; Without the following functions, spurious warnings will be generated; -;; however, they would still compile correctly because -;; `byte-compile-subr-wrong-args' also converts the call to non-inlined. - -(defun byte-compile-no-args-with-one-extra (form) - (let ((len (length form))) - (cond ((= len 1) (byte-compile-no-args form)) - ((= len 2) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "0-1"))))) - -(defun byte-compile-one-arg-with-one-extra (form) - (let ((len (length form))) - (cond ((= len 2) (byte-compile-one-arg form)) - ((= len 3) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "1-2"))))) - -(defun byte-compile-two-args-with-one-extra (form) - (let ((len (length form))) - (cond ((= len 3) (byte-compile-two-args form)) - ((= len 4) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "2-3"))))) - -(defun byte-compile-zero-or-one-arg-with-one-extra (form) - (let ((len (length form))) - (cond ((= len 1) (byte-compile-one-arg (append form '(nil)))) - ((= len 2) (byte-compile-one-arg form)) - ((= len 3) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "0-2"))))) - -(defun byte-compile-one-or-two-args-with-one-extra (form) - (let ((len (length form))) - (cond ((= len 2) (byte-compile-two-args (append form '(nil)))) - ((= len 3) (byte-compile-two-args form)) - ((= len 4) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "1-3"))))) - -(defun byte-compile-two-or-three-args-with-one-extra (form) - (let ((len (length form))) - (cond ((= len 3) (byte-compile-three-args (append form '(nil)))) - ((= len 4) (byte-compile-three-args form)) - ((= len 5) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "2-4"))))) - -(defun byte-compile-no-args-with-two-extra (form) - (let ((len (length form))) - (cond ((= len 1) (byte-compile-no-args form)) - ((or (= len 2) (= len 3)) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "0-2"))))) - -(defun byte-compile-one-arg-with-two-extra (form) - (let ((len (length form))) - (cond ((= len 2) (byte-compile-one-arg form)) - ((or (= len 3) (= len 4)) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "1-3"))))) - -;; XEmacs: used for functions that have a different opcode in v19 than v20. -;; this includes `eq', `equal', and other old-ified functions. -(defun byte-compile-two-args-19->20 (form) - (if (not (= (length form) 3)) - (byte-compile-subr-wrong-args form 2) - (byte-compile-form (car (cdr form))) ;; Push the arguments - (byte-compile-form (nth 2 form)) - (if (byte-compile-version-cond byte-compile-emacs19-compatibility) - (byte-compile-out (get (car form) 'byte-opcode19) 0) - (byte-compile-out (get (car form) 'byte-opcode) 0)))) - -(defun byte-compile-noop (form) - (byte-compile-constant nil)) - -(defun byte-compile-discard () - (byte-compile-out 'byte-discard 0)) - - -;; Compile a function that accepts one or more args and is right-associative. -;; We do it by left-associativity so that the operations -;; are done in the same order as in interpreted code. -(defun byte-compile-associative (form) - (if (cdr form) - (let ((opcode (get (car form) 'byte-opcode)) - (args (copy-sequence (cdr form)))) - (byte-compile-form (car args)) - (setq args (cdr args)) - (while args - (byte-compile-form (car args)) - (byte-compile-out opcode 0) - (setq args (cdr args)))) - (byte-compile-constant (eval form)))) - - -;; more complicated compiler macros - -(byte-defop-compiler list) -(byte-defop-compiler concat) -(byte-defop-compiler fset) -(byte-defop-compiler insert) -(byte-defop-compiler-1 function byte-compile-function-form) -(byte-defop-compiler-1 - byte-compile-minus) -(byte-defop-compiler (/ byte-quo) byte-compile-quo) -(byte-defop-compiler nconc) -(byte-defop-compiler-1 beginning-of-line) - -(defun byte-compile-buffer-substring (form) - (let ((len (length form))) - ;; buffer-substring used to take exactly two args, but now takes 0-3. - ;; convert 0-2 to two args and use special bytecode operand. - ;; convert 3 args to a normal call. - (cond ((= len 1) (setq form (append form '(nil nil))) - (= len 2) (setq form (append form '(nil))))) - (cond ((= len 3) (byte-compile-two-args form)) - ((= len 4) (byte-compile-normal-call form)) - (t (byte-compile-subr-wrong-args form "0-3"))))) - -(defun byte-compile-list (form) - (let ((count (length (cdr form)))) - (cond ((= count 0) - (byte-compile-constant nil)) - ((< count 5) - (mapcar 'byte-compile-form (cdr form)) - (byte-compile-out - (aref [byte-list1 byte-list2 byte-list3 byte-list4] (1- count)) 0)) - ((< count 256) - (mapcar 'byte-compile-form (cdr form)) - (byte-compile-out 'byte-listN count)) - (t (byte-compile-normal-call form))))) - -(defun byte-compile-concat (form) - (let ((count (length (cdr form)))) - (cond ((and (< 1 count) (< count 5)) - (mapcar 'byte-compile-form (cdr form)) - (byte-compile-out - (aref [byte-concat2 byte-concat3 byte-concat4] (- count 2)) - 0)) - ;; Concat of one arg is not a no-op if arg is not a string. - ((= count 0) - (byte-compile-form "")) - ((< count 256) - (mapcar 'byte-compile-form (cdr form)) - (byte-compile-out 'byte-concatN count)) - ((byte-compile-normal-call form))))) - -(defun byte-compile-minus (form) - (if (null (setq form (cdr form))) - (byte-compile-constant 0) - (byte-compile-form (car form)) - (if (cdr form) - (while (setq form (cdr form)) - (byte-compile-form (car form)) - (byte-compile-out 'byte-diff 0)) - (byte-compile-out 'byte-negate 0)))) - -(defun byte-compile-quo (form) - (let ((len (length form))) - (cond ((<= len 2) - (byte-compile-subr-wrong-args form "2 or more")) - (t - (byte-compile-form (car (setq form (cdr form)))) - (while (setq form (cdr form)) - (byte-compile-form (car form)) - (byte-compile-out 'byte-quo 0)))))) - -(defun byte-compile-nconc (form) - (let ((len (length form))) - (cond ((= len 1) - (byte-compile-constant nil)) - ((= len 2) - ;; nconc of one arg is a noop, even if that arg isn't a list. - (byte-compile-form (nth 1 form))) - (t - (byte-compile-form (car (setq form (cdr form)))) - (while (setq form (cdr form)) - (byte-compile-form (car form)) - (byte-compile-out 'byte-nconc 0)))))) - -(defun byte-compile-fset (form) - ;; warn about forms like (fset 'foo '(lambda () ...)) - ;; (where the lambda expression is non-trivial...) - ;; Except don't warn if the first argument is 'make-byte-code, because - ;; I'm sick of getting mail asking me whether that warning is a problem. - (let ((fn (nth 2 form)) - body) - (if (and (eq (car-safe fn) 'quote) - (eq (car-safe (setq fn (nth 1 fn))) 'lambda) - (not (eq (car-safe (cdr-safe (nth 1 form))) 'make-byte-code))) - (progn - (setq body (cdr (cdr fn))) - (if (stringp (car body)) (setq body (cdr body))) - (if (eq 'interactive (car-safe (car body))) (setq body (cdr body))) - (if (and (consp (car body)) - (not (eq 'byte-code (car (car body))))) - (byte-compile-warn - "A quoted lambda form is the second argument of fset. This is probably - not what you want, as that lambda cannot be compiled. Consider using - the syntax (function (lambda (...) ...)) instead."))))) - (byte-compile-two-args form)) - -(defun byte-compile-funarg (form) - ;; (mapcar '(lambda (x) ..) ..) ==> (mapcar (function (lambda (x) ..)) ..) - ;; for cases where it's guaranteed that first arg will be used as a lambda. - (byte-compile-normal-call - (let ((fn (nth 1 form))) - (if (and (eq (car-safe fn) 'quote) - (eq (car-safe (nth 1 fn)) 'lambda)) - (cons (car form) - (cons (cons 'function (cdr fn)) - (cdr (cdr form)))) - form)))) - -;; (function foo) must compile like 'foo, not like (symbol-function 'foo). -;; Otherwise it will be incompatible with the interpreter, -;; and (funcall (function foo)) will lose with autoloads. - -(defun byte-compile-function-form (form) - (byte-compile-constant - (cond ((symbolp (nth 1 form)) - (nth 1 form)) - ((byte-compile-lambda (nth 1 form)))))) - -(defun byte-compile-insert (form) - (cond ((null (cdr form)) - (byte-compile-constant nil)) - ((<= (length form) 256) - (mapcar 'byte-compile-form (cdr form)) - (if (cdr (cdr form)) - (byte-compile-out 'byte-insertN (length (cdr form))) - (byte-compile-out 'byte-insert 0))) - ((memq t (mapcar 'consp (cdr (cdr form)))) - (byte-compile-normal-call form)) - ;; We can split it; there is no function call after inserting 1st arg. - (t - (while (setq form (cdr form)) - (byte-compile-form (car form)) - (byte-compile-out 'byte-insert 0) - (if (cdr form) - (byte-compile-discard)))))) - -;; alas, the old (pre-19.12, and all existing versions of FSFmacs 19) -;; byte compiler will generate incorrect code for -;; (beginning-of-line nil buffer) because it buggily doesn't -;; check the number of arguments passed to beginning-of-line. - -(defun byte-compile-beginning-of-line (form) - (let ((len (length form))) - (cond ((> len 3) - (byte-compile-subr-wrong-args form "0-2")) - ((or (= len 3) (not (byte-compile-constp (nth 1 form)))) - (byte-compile-normal-call form)) - (t - (byte-compile-form - (list 'forward-line - (if (integerp (setq form (or (eval (nth 1 form)) 1))) - (1- form) - (byte-compile-warn - "Non-numeric arg to beginning-of-line: %s" form) - (list '1- (list 'quote form)))) - t) - (byte-compile-constant nil))))) - - -(byte-defop-compiler set) -(byte-defop-compiler-1 setq) -(byte-defop-compiler-1 set-default) -(byte-defop-compiler-1 setq-default) - -(byte-defop-compiler-1 quote) -(byte-defop-compiler-1 quote-form) - -(defun byte-compile-setq (form) - (let ((args (cdr form))) - (if args - (while args - (byte-compile-form (car (cdr args))) - (or for-effect (cdr (cdr args)) - (byte-compile-out 'byte-dup 0)) - (byte-compile-variable-ref 'byte-varset (car args)) - (setq args (cdr (cdr args)))) - ;; (setq), with no arguments. - (byte-compile-form nil for-effect)) - (setq for-effect nil))) - -(defun byte-compile-set (form) - ;; Compile (set 'foo x) as (setq foo x) for trivially better code and so - ;; that we get applicable warnings. Compile everything else (including - ;; malformed calls) like a normal 2-arg byte-coded function. - (if (or (not (eq (car-safe (nth 1 form)) 'quote)) - (not (= (length form) 3)) - (not (= (length (nth 1 form)) 2))) - (byte-compile-two-args form) - (byte-compile-setq (list 'setq (nth 1 (nth 1 form)) (nth 2 form))))) - -(defun byte-compile-setq-default (form) - (let ((rest (cdr form))) - ;; emit multiple calls to set-default if necessary - (while rest - (byte-compile-form - (list 'set-default (list 'quote (car rest)) (car (cdr rest))) - (not (null (cdr (cdr rest))))) - (setq rest (cdr (cdr rest)))))) - -(defun byte-compile-set-default (form) - (let ((rest (cdr form))) - (if (cdr (cdr (cdr form))) - ;; emit multiple calls to set-default if necessary; all but last - ;; for-effect (this recurses.) - (while rest - (byte-compile-form - (list 'set-default (car rest) (car (cdr rest))) - (not (null (cdr rest)))) - (setq rest (cdr (cdr rest)))) - ;; else, this is the one-armed version - (let ((var (nth 1 form)) - ;;(val (nth 2 form)) - ) - ;; notice calls to set-default/setq-default for variables which - ;; have not been declared with defvar/defconst. - (if (and (memq 'free-vars byte-compile-warnings) - (or (null var) - (and (eq (car-safe var) 'quote) - (= 2 (length var))))) - (let ((sym (nth 1 var)) - cell) - (or (and sym (symbolp sym) (globally-boundp sym)) - (and (setq cell (assq sym byte-compile-bound-variables)) - (setcdr cell (logior (cdr cell) - byte-compile-assigned-bit))) - (memq sym byte-compile-free-assignments) - (if (or (not (symbolp sym)) (memq sym '(t nil))) - (progn - (byte-compile-warn - "Attempt to set-globally %s %s" - (if (symbolp sym) "constant" "nonvariable") - (prin1-to-string sym))) - (progn - (byte-compile-warn "assignment to free variable %s" sym) - (setq byte-compile-free-assignments - (cons sym byte-compile-free-assignments))))))) - ;; now emit a normal call to set-default (or possibly multiple calls) - (byte-compile-normal-call form))))) - - -(defun byte-compile-quote (form) - (byte-compile-constant (car (cdr form)))) - -(defun byte-compile-quote-form (form) - (byte-compile-constant (byte-compile-top-level (nth 1 form)))) - - -;;; control structures - -(defun byte-compile-body (body &optional for-effect) - (while (cdr body) - (byte-compile-form (car body) t) - (setq body (cdr body))) - (byte-compile-form (car body) for-effect)) - -(proclaim-inline byte-compile-body-do-effect) -(defun byte-compile-body-do-effect (body) - (byte-compile-body body for-effect) - (setq for-effect nil)) - -(proclaim-inline byte-compile-form-do-effect) -(defun byte-compile-form-do-effect (form) - (byte-compile-form form for-effect) - (setq for-effect nil)) - -(byte-defop-compiler-1 inline byte-compile-progn) -(byte-defop-compiler-1 progn) -(byte-defop-compiler-1 prog1) -(byte-defop-compiler-1 prog2) -(byte-defop-compiler-1 if) -(byte-defop-compiler-1 cond) -(byte-defop-compiler-1 and) -(byte-defop-compiler-1 or) -(byte-defop-compiler-1 while) -(byte-defop-compiler-1 funcall) -(byte-defop-compiler-1 apply byte-compile-funarg) -(byte-defop-compiler-1 mapcar byte-compile-funarg) -(byte-defop-compiler-1 mapatoms byte-compile-funarg) -(byte-defop-compiler-1 mapconcat byte-compile-funarg) -(byte-defop-compiler-1 let) -(byte-defop-compiler-1 let*) - -(defun byte-compile-progn (form) - (byte-compile-body-do-effect (cdr form))) - -(defun byte-compile-prog1 (form) - (byte-compile-form-do-effect (car (cdr form))) - (byte-compile-body (cdr (cdr form)) t)) - -(defun byte-compile-prog2 (form) - (byte-compile-form (nth 1 form) t) - (byte-compile-form-do-effect (nth 2 form)) - (byte-compile-body (cdr (cdr (cdr form))) t)) - -(defmacro byte-compile-goto-if (cond discard tag) - (` (byte-compile-goto - (if (, cond) - (if (, discard) 'byte-goto-if-not-nil 'byte-goto-if-not-nil-else-pop) - (if (, discard) 'byte-goto-if-nil 'byte-goto-if-nil-else-pop)) - (, tag)))) - -(defun byte-compile-if (form) - (byte-compile-form (car (cdr form))) - (if (null (nthcdr 3 form)) - ;; No else-forms - (let ((donetag (byte-compile-make-tag))) - (byte-compile-goto-if nil for-effect donetag) - (byte-compile-form (nth 2 form) for-effect) - (byte-compile-out-tag donetag)) - (let ((donetag (byte-compile-make-tag)) (elsetag (byte-compile-make-tag))) - (byte-compile-goto 'byte-goto-if-nil elsetag) - (byte-compile-form (nth 2 form) for-effect) - (byte-compile-goto 'byte-goto donetag) - (byte-compile-out-tag elsetag) - (byte-compile-body (cdr (cdr (cdr form))) for-effect) - (byte-compile-out-tag donetag))) - (setq for-effect nil)) - -(defun byte-compile-cond (clauses) - (let ((donetag (byte-compile-make-tag)) - nexttag clause) - (while (setq clauses (cdr clauses)) - (setq clause (car clauses)) - (cond ((or (eq (car clause) t) - (and (eq (car-safe (car clause)) 'quote) - (car-safe (cdr-safe (car clause))))) - ;; Unconditional clause - (setq clause (cons t clause) - clauses nil)) - ((cdr clauses) - (byte-compile-form (car clause)) - (if (null (cdr clause)) - ;; First clause is a singleton. - (byte-compile-goto-if t for-effect donetag) - (setq nexttag (byte-compile-make-tag)) - (byte-compile-goto 'byte-goto-if-nil nexttag) - (byte-compile-body (cdr clause) for-effect) - (byte-compile-goto 'byte-goto donetag) - (byte-compile-out-tag nexttag))))) - ;; Last clause - (and (cdr clause) (not (eq (car clause) t)) - (progn (byte-compile-form (car clause)) - (byte-compile-goto-if nil for-effect donetag) - (setq clause (cdr clause)))) - (byte-compile-body-do-effect clause) - (byte-compile-out-tag donetag))) - -(defun byte-compile-and (form) - (let ((failtag (byte-compile-make-tag)) - (args (cdr form))) - (if (null args) - (byte-compile-form-do-effect t) - (while (cdr args) - (byte-compile-form (car args)) - (byte-compile-goto-if nil for-effect failtag) - (setq args (cdr args))) - (byte-compile-form-do-effect (car args)) - (byte-compile-out-tag failtag)))) - -(defun byte-compile-or (form) - (let ((wintag (byte-compile-make-tag)) - (args (cdr form))) - (if (null args) - (byte-compile-form-do-effect nil) - (while (cdr args) - (byte-compile-form (car args)) - (byte-compile-goto-if t for-effect wintag) - (setq args (cdr args))) - (byte-compile-form-do-effect (car args)) - (byte-compile-out-tag wintag)))) - -(defun byte-compile-while (form) - (let ((endtag (byte-compile-make-tag)) - (looptag (byte-compile-make-tag))) - (byte-compile-out-tag looptag) - (byte-compile-form (car (cdr form))) - (byte-compile-goto-if nil for-effect endtag) - (byte-compile-body (cdr (cdr form)) t) - (byte-compile-goto 'byte-goto looptag) - (byte-compile-out-tag endtag) - (setq for-effect nil))) - -(defun byte-compile-funcall (form) - (mapcar 'byte-compile-form (cdr form)) - (byte-compile-out 'byte-call (length (cdr (cdr form))))) - - -(defun byte-compile-let (form) - ;; First compute the binding values in the old scope. - (let ((varlist (car (cdr form)))) - (while varlist - (if (consp (car varlist)) - (byte-compile-form (car (cdr (car varlist)))) - (byte-compile-push-constant nil)) - (setq varlist (cdr varlist)))) - (let ((byte-compile-bound-variables - (cons 'new-scope byte-compile-bound-variables)) - (varlist (reverse (car (cdr form)))) - (extra-flags - ;; If this let is of the form (let (...) (byte-code ...)) - ;; then assume that it is the result of a transformation of - ;; ((lambda (...) (byte-code ... )) ...) and thus compile - ;; the variable bindings as if they were arglist bindings - ;; (which matters for what warnings.) - (if (eq 'byte-code (car-safe (nth 2 form))) - byte-compile-arglist-bit - nil))) - (while varlist - (byte-compile-variable-ref 'byte-varbind - (if (consp (car varlist)) - (car (car varlist)) - (car varlist)) - extra-flags) - (setq varlist (cdr varlist))) - (byte-compile-body-do-effect (cdr (cdr form))) - (if (memq 'unused-vars byte-compile-warnings) - ;; done compiling in this scope, warn now. - (byte-compile-warn-about-unused-variables)) - (byte-compile-out 'byte-unbind (length (car (cdr form)))))) - -(defun byte-compile-let* (form) - (let ((byte-compile-bound-variables - (cons 'new-scope byte-compile-bound-variables)) - (varlist (copy-sequence (car (cdr form))))) - (while varlist - (if (atom (car varlist)) - (byte-compile-push-constant nil) - (byte-compile-form (car (cdr (car varlist)))) - (setcar varlist (car (car varlist)))) - (byte-compile-variable-ref 'byte-varbind (car varlist)) - (setq varlist (cdr varlist))) - (byte-compile-body-do-effect (cdr (cdr form))) - (if (memq 'unused-vars byte-compile-warnings) - ;; done compiling in this scope, warn now. - (byte-compile-warn-about-unused-variables)) - (byte-compile-out 'byte-unbind (length (car (cdr form)))))) - - -(byte-defop-compiler-1 /= byte-compile-negated) -(byte-defop-compiler-1 atom byte-compile-negated) -(byte-defop-compiler-1 nlistp byte-compile-negated) - -(put '/= 'byte-compile-negated-op '=) -(put 'atom 'byte-compile-negated-op 'consp) -(put 'nlistp 'byte-compile-negated-op 'listp) - -(defun byte-compile-negated (form) - (byte-compile-form-do-effect (byte-compile-negation-optimizer form))) - -;; Even when optimization is off, /= is optimized to (not (= ...)). -(defun byte-compile-negation-optimizer (form) - ;; an optimizer for forms where is less efficient than (not ) - (list 'not - (cons (or (get (car form) 'byte-compile-negated-op) - (error - "Compiler error: `%s' has no `byte-compile-negated-op' property" - (car form))) - (cdr form)))) - -;;; other tricky macro-like special-forms - -(byte-defop-compiler-1 catch) -(byte-defop-compiler-1 unwind-protect) -(byte-defop-compiler-1 condition-case) -(byte-defop-compiler-1 save-excursion) -(byte-defop-compiler-1 save-current-buffer) -(byte-defop-compiler-1 save-restriction) -(byte-defop-compiler-1 save-window-excursion) -(byte-defop-compiler-1 with-output-to-temp-buffer) -;; no track-mouse. - -(defun byte-compile-catch (form) - (byte-compile-form (car (cdr form))) - (byte-compile-push-constant - (byte-compile-top-level (cons 'progn (cdr (cdr form))) for-effect)) - (byte-compile-out 'byte-catch 0)) - -(defun byte-compile-unwind-protect (form) - (byte-compile-push-constant - (byte-compile-top-level-body (cdr (cdr form)) t)) - (byte-compile-out 'byte-unwind-protect 0) - (byte-compile-form-do-effect (car (cdr form))) - (byte-compile-out 'byte-unbind 1)) - -;;(defun byte-compile-track-mouse (form) -;; (byte-compile-form -;; (list -;; 'funcall -;; (list 'quote -;; (list 'lambda nil -;; (cons 'track-mouse -;; (byte-compile-top-level-body (cdr form)))))))) - -(defun byte-compile-condition-case (form) - (let* ((var (nth 1 form)) - (byte-compile-bound-variables - (if var - (cons (cons var 0) - (cons 'new-scope byte-compile-bound-variables)) - (cons 'new-scope byte-compile-bound-variables)))) - (or (symbolp var) - (byte-compile-warn - "%s is not a variable-name or nil (in condition-case)" - (prin1-to-string var))) - (byte-compile-push-constant var) - (byte-compile-push-constant (byte-compile-top-level - (nth 2 form) for-effect)) - (let ((clauses (cdr (cdr (cdr form)))) - compiled-clauses) - (while clauses - (let* ((clause (car clauses)) - (condition (car clause))) - (cond ((not (or (symbolp condition) - (and (listp condition) - (let ((syms condition) (ok t)) - (while syms - (if (not (symbolp (car syms))) - (setq ok nil)) - (setq syms (cdr syms))) - ok)))) - (byte-compile-warn - "%s is not a symbol naming a condition or a list of such (in condition-case)" - (prin1-to-string condition))) -;; ((not (or (eq condition 't) -;; (and (stringp (get condition 'error-message)) -;; (consp (get condition 'error-conditions))))) -;; (byte-compile-warn -;; "%s is not a known condition name (in condition-case)" -;; condition)) - ) - (setq compiled-clauses - (cons (cons condition - (byte-compile-top-level-body - (cdr clause) for-effect)) - compiled-clauses))) - (setq clauses (cdr clauses))) - (byte-compile-push-constant (nreverse compiled-clauses))) - (if (memq 'unused-vars byte-compile-warnings) - ;; done compiling in this scope, warn now. - (byte-compile-warn-about-unused-variables)) - (byte-compile-out 'byte-condition-case 0))) - - -(defun byte-compile-save-excursion (form) - (byte-compile-out 'byte-save-excursion 0) - (byte-compile-body-do-effect (cdr form)) - (byte-compile-out 'byte-unbind 1)) - -(defun byte-compile-save-restriction (form) - (byte-compile-out 'byte-save-restriction 0) - (byte-compile-body-do-effect (cdr form)) - (byte-compile-out 'byte-unbind 1)) - -(defun byte-compile-save-current-buffer (form) - (if (byte-compile-version-cond byte-compile-emacs19-compatibility) - ;; `save-current-buffer' special form is not available in XEmacs 19. - (byte-compile-form - `(let ((_byte_compiler_save_buffer_emulation_closure_ (current-buffer))) - (unwind-protect - (progn ,@(cdr form)) - (and (buffer-live-p _byte_compiler_save_buffer_emulation_closure_) - (set-buffer _byte_compiler_save_buffer_emulation_closure_))))) - (byte-compile-out 'byte-save-current-buffer 0) - (byte-compile-body-do-effect (cdr form)) - (byte-compile-out 'byte-unbind 1))) - -(defun byte-compile-save-window-excursion (form) - (byte-compile-push-constant - (byte-compile-top-level-body (cdr form) for-effect)) - (byte-compile-out 'byte-save-window-excursion 0)) - -(defun byte-compile-with-output-to-temp-buffer (form) - (byte-compile-form (car (cdr form))) - (byte-compile-out 'byte-temp-output-buffer-setup 0) - (byte-compile-body (cdr (cdr form))) - (byte-compile-out 'byte-temp-output-buffer-show 0)) - - -;;; top-level forms elsewhere - -(byte-defop-compiler-1 defun) -(byte-defop-compiler-1 defmacro) -(byte-defop-compiler-1 defvar) -(byte-defop-compiler-1 defconst byte-compile-defvar) -(byte-defop-compiler-1 autoload) -;; According to Mly this can go now that lambda is a macro -;(byte-defop-compiler-1 lambda byte-compile-lambda-form) -(byte-defop-compiler-1 defalias) -(byte-defop-compiler-1 define-function) - -(defun byte-compile-defun (form) - ;; This is not used for file-level defuns with doc strings. - (byte-compile-two-args ; Use this to avoid byte-compile-fset's warning. - (list 'fset (list 'quote (nth 1 form)) - (byte-compile-byte-code-maker - (byte-compile-lambda (cons 'lambda (cdr (cdr form))))))) - (byte-compile-discard) - (byte-compile-constant (nth 1 form))) - -(defun byte-compile-defmacro (form) - ;; This is not used for file-level defmacros with doc strings. - (byte-compile-body-do-effect - (list (list 'fset (list 'quote (nth 1 form)) - (let ((code (byte-compile-byte-code-maker - (byte-compile-lambda - (cons 'lambda (cdr (cdr form))))))) - (if (eq (car-safe code) 'make-byte-code) - (list 'cons ''macro code) - (list 'quote (cons 'macro (eval code)))))) - (list 'quote (nth 1 form))))) - -(defun byte-compile-defvar (form) - ;; This is not used for file-level defvar/consts with doc strings: - ;; byte-compile-file-form-defvar will be used in that case. - (let ((var (nth 1 form)) - (value (nth 2 form)) - (string (nth 3 form))) - (if (> (length form) 4) - (byte-compile-warn "%s used with too many args" (car form))) - (if (memq 'free-vars byte-compile-warnings) - (setq byte-compile-bound-variables - (cons (cons var byte-compile-global-bit) - byte-compile-bound-variables))) - (byte-compile-body-do-effect - (list (if (cdr (cdr form)) - (if (eq (car form) 'defconst) - (list 'setq var value) - (list 'or (list 'boundp (list 'quote var)) - (list 'setq var value)))) - ;; Put the defined variable in this library's load-history entry - ;; just as a real defvar would. - (list 'setq 'current-load-list - (list 'cons (list 'quote var) - 'current-load-list)) - (if string - (list 'put (list 'quote var) ''variable-documentation string)) - (list 'quote var))))) - -(defun byte-compile-autoload (form) - (and (byte-compile-constp (nth 1 form)) - (byte-compile-constp (nth 5 form)) - (memq (eval (nth 5 form)) '(t macro)) ; macro-p - (not (fboundp (eval (nth 1 form)))) - (byte-compile-warn - "The compiler ignores `autoload' except at top level. You should - probably put the autoload of the macro `%s' at top-level." - (eval (nth 1 form)))) - (byte-compile-normal-call form)) - -;; Lambda's in valid places are handled as special cases by various code. -;; The ones that remain are errors. -;; According to Mly this can go now that lambda is a macro -;(defun byte-compile-lambda-form (form) -; (byte-compile-warn -; "`lambda' used in function position is invalid: probably you mean #'%s" -; (let ((print-escape-newlines t) -; (print-level 4) -; (print-length 4)) -; (prin1-to-string form))) -; (byte-compile-normal-call -; (list 'signal ''error -; (list 'quote (list "`lambda' used in function position" form))))) - -;; Compile normally, but deal with warnings for the function being defined. -(defun byte-compile-defalias (form) - (if (and (consp (cdr form)) (consp (nth 1 form)) - (eq (car (nth 1 form)) 'quote) - (consp (cdr (nth 1 form))) - (symbolp (nth 1 (nth 1 form))) - (consp (nthcdr 2 form)) - (consp (nth 2 form)) - (eq (car (nth 2 form)) 'quote) - (consp (cdr (nth 2 form))) - (symbolp (nth 1 (nth 2 form)))) - (progn - (byte-compile-defalias-warn (nth 1 (nth 1 form)) - (nth 1 (nth 2 form))) - (setq byte-compile-function-environment - (cons (cons (nth 1 (nth 1 form)) - (nth 1 (nth 2 form))) - byte-compile-function-environment)))) - (byte-compile-normal-call form)) - -(defun byte-compile-define-function (form) - (byte-compile-defalias form)) - -;; Turn off warnings about prior calls to the function being defalias'd. -;; This could be smarter and compare those calls with -;; the function it is being aliased to. -(defun byte-compile-defalias-warn (new alias) - (let ((calls (assq new byte-compile-unresolved-functions))) - (if calls - (setq byte-compile-unresolved-functions - (delq calls byte-compile-unresolved-functions))))) - -;;; tags - -;; Note: Most operations will strip off the 'TAG, but it speeds up -;; optimization to have the 'TAG as a part of the tag. -;; Tags will be (TAG . (tag-number . stack-depth)). -(defun byte-compile-make-tag () - (list 'TAG (setq byte-compile-tag-number (1+ byte-compile-tag-number)))) - - -(defun byte-compile-out-tag (tag) - (setq byte-compile-output (cons tag byte-compile-output)) - (if (cdr (cdr tag)) - (progn - ;; ## remove this someday - (and byte-compile-depth - (not (= (cdr (cdr tag)) byte-compile-depth)) - (error "Compiler bug: depth conflict at tag %d" (car (cdr tag)))) - (setq byte-compile-depth (cdr (cdr tag)))) - (setcdr (cdr tag) byte-compile-depth))) - -(defun byte-compile-goto (opcode tag) - (setq byte-compile-output (cons (cons opcode tag) byte-compile-output)) - (setcdr (cdr tag) (if (memq opcode byte-goto-always-pop-ops) - (1- byte-compile-depth) - byte-compile-depth)) - (setq byte-compile-depth (and (not (eq opcode 'byte-goto)) - (1- byte-compile-depth)))) - -(defun byte-compile-out (opcode offset) - (setq byte-compile-output (cons (cons opcode offset) byte-compile-output)) - (cond ((eq opcode 'byte-call) - (setq byte-compile-depth (- byte-compile-depth offset))) - ((eq opcode 'byte-return) - ;; This is actually an unnecessary case, because there should be - ;; no more opcodes behind byte-return. - (setq byte-compile-depth nil)) - (t - (setq byte-compile-depth (+ byte-compile-depth - (or (aref byte-stack+-info - (symbol-value opcode)) - (- (1- offset)))) - byte-compile-maxdepth (max byte-compile-depth - byte-compile-maxdepth)))) - ;;(if (< byte-compile-depth 0) (error "Compiler error: stack underflow")) - ) - - -;;; call tree stuff - -(defun byte-compile-annotate-call-tree (form) - (let (entry) - ;; annotate the current call - (if (setq entry (assq (car form) byte-compile-call-tree)) - (or (memq byte-compile-current-form (nth 1 entry)) ;callers - (setcar (cdr entry) - (cons byte-compile-current-form (nth 1 entry)))) - (setq byte-compile-call-tree - (cons (list (car form) (list byte-compile-current-form) nil) - byte-compile-call-tree))) - ;; annotate the current function - (if (setq entry (assq byte-compile-current-form byte-compile-call-tree)) - (or (memq (car form) (nth 2 entry)) ;called - (setcar (cdr (cdr entry)) - (cons (car form) (nth 2 entry)))) - (setq byte-compile-call-tree - (cons (list byte-compile-current-form nil (list (car form))) - byte-compile-call-tree))) - )) - -;; Renamed from byte-compile-report-call-tree -;; to avoid interfering with completion of byte-compile-file. -;;;###autoload -(defun display-call-tree (&optional filename) - "Display a call graph of a specified file. -This lists which functions have been called, what functions called -them, and what functions they call. The list includes all functions -whose definitions have been compiled in this Emacs session, as well as -all functions called by those functions. - -The call graph does not include macros, inline functions, or -primitives that the byte-code interpreter knows about directly \(eq, -cons, etc.\). - -The call tree also lists those functions which are not known to be called -\(that is, to which no calls have been compiled\), and which cannot be -invoked interactively." - (interactive) - (message "Generating call tree...") - (with-output-to-temp-buffer "*Call-Tree*" - (set-buffer "*Call-Tree*") - (erase-buffer) - (message "Generating call tree... (sorting on %s)" - byte-compile-call-tree-sort) - (insert "Call tree for " - (cond ((null byte-compile-current-file) (or filename "???")) - ((stringp byte-compile-current-file) - byte-compile-current-file) - (t (buffer-name byte-compile-current-file))) - " sorted on " - (prin1-to-string byte-compile-call-tree-sort) - ":\n\n") - (if byte-compile-call-tree-sort - (setq byte-compile-call-tree - (sort byte-compile-call-tree - (cond - ((eq byte-compile-call-tree-sort 'callers) - (function (lambda (x y) (< (length (nth 1 x)) - (length (nth 1 y)))))) - ((eq byte-compile-call-tree-sort 'calls) - (function (lambda (x y) (< (length (nth 2 x)) - (length (nth 2 y)))))) - ((eq byte-compile-call-tree-sort 'calls+callers) - (function (lambda (x y) (< (+ (length (nth 1 x)) - (length (nth 2 x))) - (+ (length (nth 1 y)) - (length (nth 2 y))))))) - ((eq byte-compile-call-tree-sort 'name) - (function (lambda (x y) (string< (car x) - (car y))))) - (t (error - "`byte-compile-call-tree-sort': `%s' - unknown sort mode" - byte-compile-call-tree-sort)))))) - (message "Generating call tree...") - (let ((rest byte-compile-call-tree) - (b (current-buffer)) - f p - callers calls) - (while rest - (prin1 (car (car rest)) b) - (setq callers (nth 1 (car rest)) - calls (nth 2 (car rest))) - (insert "\t" - (cond ((not (fboundp (setq f (car (car rest))))) - (if (null f) - " ";; shouldn't insert nil then, actually -sk - " ")) - ((subrp (setq f (symbol-function f))) - " ") - ((symbolp f) - (format " ==> %s" f)) - ((compiled-function-p f) - "") - ((not (consp f)) - "") - ((eq 'macro (car f)) - (if (or (compiled-function-p (cdr f)) - (assq 'byte-code (cdr (cdr (cdr f))))) - " " - " ")) - ((assq 'byte-code (cdr (cdr f))) - "") - ((eq 'lambda (car f)) - "") - (t "???")) - (format " (%d callers + %d calls = %d)" - ;; Does the optimizer eliminate common subexpressions?-sk - (length callers) - (length calls) - (+ (length callers) (length calls))) - "\n") - (if callers - (progn - (insert " called by:\n") - (setq p (point)) - (insert " " (if (car callers) - (mapconcat 'symbol-name callers ", ") - "")) - (let ((fill-prefix " ")) - (fill-region-as-paragraph p (point))))) - (if calls - (progn - (insert " calls:\n") - (setq p (point)) - (insert " " (mapconcat 'symbol-name calls ", ")) - (let ((fill-prefix " ")) - (fill-region-as-paragraph p (point))))) - (insert "\n") - (setq rest (cdr rest))) - - (message "Generating call tree...(finding uncalled functions...)") - (setq rest byte-compile-call-tree) - (let ((uncalled nil)) - (while rest - (or (nth 1 (car rest)) - (null (setq f (car (car rest)))) - (byte-compile-fdefinition f t) - (commandp (byte-compile-fdefinition f nil)) - (setq uncalled (cons f uncalled))) - (setq rest (cdr rest))) - (if uncalled - (let ((fill-prefix " ")) - (insert "Noninteractive functions not known to be called:\n ") - (setq p (point)) - (insert (mapconcat 'symbol-name (nreverse uncalled) ", ")) - (fill-region-as-paragraph p (point))))) - ) - (message "Generating call tree...done.") - )) - - -;;; by crl@newton.purdue.edu -;;; Only works noninteractively. -;;;###autoload -(defun batch-byte-compile () - "Run `byte-compile-file' on the files remaining on the command line. -Use this from the command line, with `-batch'; -it won't work in an interactive Emacs. -Each file is processed even if an error occurred previously. -For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\"" - ;; command-line-args-left is what is left of the command line (from - ;; startup.el) - (defvar command-line-args-left) ;Avoid 'free variable' warning - (if (not noninteractive) - (error "`batch-byte-compile' is to be used only with -batch")) - (let ((error nil) - (debug-issue-ebola-notices 0)) ; Hack -slb - (while command-line-args-left - (if (file-directory-p (expand-file-name (car command-line-args-left))) - (let ((files (directory-files (car command-line-args-left))) - source dest) - (while files - (if (and (string-match emacs-lisp-file-regexp (car files)) - (not (auto-save-file-name-p (car files))) - (setq source (expand-file-name - (car files) - (car command-line-args-left))) - (setq dest (byte-compile-dest-file source)) - (file-exists-p dest) - (file-newer-than-file-p source dest)) - (if (null (batch-byte-compile-1 source)) - (setq error t))) - (setq files (cdr files)))) - (if (null (batch-byte-compile-1 (car command-line-args-left))) - (setq error t))) - (setq command-line-args-left (cdr command-line-args-left))) - (message "Done") - (kill-emacs (if error 1 0)))) - -(defun batch-byte-compile-1 (file) - (condition-case err - (progn (byte-compile-file file) t) - (error - (princ ">>Error occurred processing ") - (princ file) - (princ ": ") - (if (fboundp 'display-error) ; XEmacs 19.8+ - (display-error err nil) - (princ (or (get (car err) 'error-message) (car err))) - (mapcar '(lambda (x) (princ " ") (prin1 x)) (cdr err))) - (princ "\n") - nil))) - -;;;###autoload -(defun batch-byte-recompile-directory-norecurse () - "Same as `batch-byte-recompile-directory' but without recursion." - (setq byte-recompile-directory-recursively nil) - (batch-byte-recompile-directory)) - -;;;###autoload -(defun batch-byte-recompile-directory () - "Runs `byte-recompile-directory' on the dirs remaining on the command line. -Must be used only with `-batch', and kills Emacs on completion. -For example, invoke `xemacs -batch -f batch-byte-recompile-directory .'." - ;; command-line-args-left is what is left of the command line (startup.el) - (defvar command-line-args-left) ;Avoid 'free variable' warning - (if (not noninteractive) - (error "batch-byte-recompile-directory is to be used only with -batch")) - (or command-line-args-left - (setq command-line-args-left '("."))) - (let ((byte-recompile-directory-ignore-errors-p t) - (debug-issue-ebola-notices 0)) - (while command-line-args-left - (byte-recompile-directory (car command-line-args-left)) - (setq command-line-args-left (cdr command-line-args-left)))) - (kill-emacs 0)) - -(make-obsolete 'elisp-compile-defun 'compile-defun) -(make-obsolete 'byte-compile-report-call-tree 'display-call-tree) - -;; other make-obsolete calls in obsolete.el. - -(provide 'byte-compile) -(provide 'bytecomp) - - -;;; report metering (see the hacks in bytecode.c) - -(if (boundp 'byte-code-meter) - (defun byte-compile-report-ops () - (defvar byte-code-meter) - (with-output-to-temp-buffer "*Meter*" - (set-buffer "*Meter*") - (let ((i 0) n op off) - (while (< i 256) - (setq n (aref (aref byte-code-meter 0) i) - off nil) - (if t ;(not (zerop n)) - (progn - (setq op i) - (setq off nil) - (cond ((< op byte-nth) - (setq off (logand op 7)) - (setq op (logand op 248))) - ((>= op byte-constant) - (setq off (- op byte-constant) - op byte-constant))) - (setq op (aref byte-code-vector op)) - (insert (format "%-4d" i)) - (insert (symbol-name op)) - (if off (insert " [" (int-to-string off) "]")) - (indent-to 40) - (insert (int-to-string n) "\n"))) - (setq i (1+ i))))))) - - -;; To avoid "lisp nesting exceeds max-lisp-eval-depth" when bytecomp compiles -;; itself, compile some of its most used recursive functions (at load time). -;; -(eval-when-compile - (or (compiled-function-p (symbol-function 'byte-compile-form)) - (assq 'byte-code (symbol-function 'byte-compile-form)) - (let ((byte-optimize nil) ; do it fast - (byte-compile-warnings nil)) - (mapcar '(lambda (x) - (or noninteractive (message "compiling %s..." x)) - (byte-compile x) - (or noninteractive (message "compiling %s...done" x))) - '(byte-compile-normal-call - byte-compile-form - byte-compile-body - ;; Inserted some more than necessary, to speed it up. - byte-compile-top-level - byte-compile-out-toplevel - byte-compile-constant - byte-compile-variable-ref)))) - nil) - -;;; bytecomp.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/bytecomp/disass.el --- a/lisp/bytecomp/disass.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,272 +0,0 @@ -;;; disass.el --- disassembler for compiled Emacs Lisp code - -;;; Copyright (C) 1986, 1991-1994 Free Software Foundation, Inc. - -;; Author: Doug Cutting -;; Jamie Zawinski -;; Maintainer: Jamie Zawinski -;; Keywords: internal - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.28. - -;;; Commentary: - -;; The single entry point, `disassemble', disassembles a code object generated -;; by the Emacs Lisp byte-compiler. This doesn't invert the compilation -;; operation, not by a long shot, but it's useful for debugging. - -;; -;; Original version by Doug Cutting (doug@csli.stanford.edu) -;; Substantially modified by Jamie Zawinski for -;; the new lapcode-based byte compiler. - -;;; Code: - -;;; The variable byte-code-vector is defined by the new bytecomp.el. -;;; The function byte-decompile-lapcode is defined in byte-opt.el. -;;; Since we don't use byte-decompile-lapcode, let's try not loading byte-opt. -;;; The variable byte-code-vector is defined by the new bytecomp.el. -;;; The function byte-decompile-lapcode is defined in byte-optimize.el. -(require 'byte-optimize) - -(defvar disassemble-column-1-indent 8 "*") -(defvar disassemble-column-2-indent 10 "*") -(defvar disassemble-recursive-indent 3 "*") - - -;;;###autoload -(defun disassemble (object &optional buffer indent interactive-p) - "Print disassembled code for OBJECT in (optional) BUFFER. -OBJECT can be a symbol defined as a function, or a function itself -\(a lambda expression or a compiled-function object). -If OBJECT is not already compiled, we compile it, but do not -redefine OBJECT if it is a symbol." - (interactive (list (intern (completing-read "Disassemble function: " - obarray 'fboundp t)) - nil 0 t)) - (if (eq (car-safe object) 'byte-code) - (setq object (list 'lambda () object))) - (or indent (setq indent 0)) ;Default indent to zero - (save-excursion - (if (or interactive-p (null buffer)) - (with-output-to-temp-buffer "*Disassemble*" - (set-buffer "*Disassemble*") - (disassemble-internal object indent (not interactive-p))) - (set-buffer buffer) - (disassemble-internal object indent nil))) - nil) - - -(defun disassemble-internal (obj indent interactive-p) - (let ((macro 'nil) - (name 'nil) - args) - (while (symbolp obj) - (setq name obj - obj (symbol-function obj))) - (if (subrp obj) - (error "Can't disassemble #" name)) - (if (eq (car-safe obj) 'autoload) - (progn - (load (elt obj 1)) - (setq obj (symbol-function name)))) - (if (eq (car-safe obj) 'macro) ;handle macros - (setq macro t - obj (cdr obj))) - (if (and (listp obj) (eq (car obj) 'byte-code)) - (setq obj (list 'lambda nil obj))) - (if (and (listp obj) (not (eq (car obj) 'lambda))) - (error "not a function")) - (if (consp obj) - (if (assq 'byte-code obj) - nil - (if interactive-p (message (if name - "Compiling %s's definition..." - "Compiling definition...") - name)) - (setq obj (byte-compile obj)) - (if interactive-p (message "Done compiling. Disassembling...")))) - (cond ((consp obj) - (setq obj (cdr obj)) ;throw lambda away - (setq args (car obj)) ;save arg list - (setq obj (cdr obj))) - (t - (setq args (compiled-function-arglist obj)))) - (if (zerop indent) ; not a nested function - (progn - (indent-to indent) - (insert (format "byte code%s%s%s:\n" - (if (or macro name) " for" "") - (if macro " macro" "") - (if name (format " %s" name) ""))))) - (let ((doc (if (consp obj) - (and (stringp (car obj)) (car obj)) - (condition-case error - (documentation obj) - (error (format "%S" error)))))) - (if (and doc (stringp doc)) - (progn (and (consp obj) (setq obj (cdr obj))) - (indent-to indent) - (princ " doc: " (current-buffer)) - (let ((frobbed nil)) - (if (string-match "\n" doc) - (setq doc (substring doc 0 (match-beginning 0)) - frobbed t)) - (if (> (length doc) 70) - (setq doc (substring doc 0 65) frobbed t)) - (if frobbed (setq doc (concat doc " ...")))) - (insert doc "\n")))) - (indent-to indent) - (insert " args: ") - (prin1 args (current-buffer)) - (insert "\n") - (if (condition-case () - (commandp obj) ; ie interactivep - (error nil)) - (let ((interactive (if (consp obj) - (elt (assq 'interactive obj) 1) - (elt (compiled-function-interactive obj) 1)))) - (if (eq (car-safe (car-safe obj)) 'interactive) - (setq obj (cdr obj))) - (indent-to indent) - (insert " interactive: ") - (if (eq (car-safe interactive) 'byte-code) - (progn - (insert "\n") - (disassemble-1 interactive - (+ indent disassemble-recursive-indent))) - (let ((print-escape-newlines t)) - (prin1 interactive (current-buffer)))) - (insert "\n"))) - (cond ((and (consp obj) (assq 'byte-code obj)) - (disassemble-1 (assq 'byte-code obj) indent)) - ((compiled-function-p obj) - (disassemble-1 obj indent)) - (t - (insert "Uncompiled body: ") - (let ((print-escape-newlines t)) - (prin1 (if (cdr obj) (cons 'progn obj) (car obj)) - (current-buffer)))))) - (if interactive-p - (message nil))) - - -(defun disassemble-1 (obj indent) - "Prints the byte-code call OBJ in the current buffer. -OBJ should be a call to BYTE-CODE generated by the byte compiler." - (let (bytes constvec) - (if (consp obj) - (setq bytes (car (cdr obj)) ; the byte code - constvec (car (cdr (cdr obj)))) ; constant vector - (setq bytes (compiled-function-instructions obj) - constvec (compiled-function-constants obj))) - (let ((lap (byte-decompile-bytecode bytes constvec)) - op arg opname pc-value) - (let ((tagno 0) - tmp - (lap lap)) - (while (setq tmp (assq 'TAG lap)) - (setcar (cdr tmp) (setq tagno (1+ tagno))) - (setq lap (cdr (memq tmp lap))))) - (while lap - ;; Take off the pc value of the next thing - ;; and put it in pc-value. - (setq pc-value nil) - (if (numberp (car lap)) - (setq pc-value (car lap) - lap (cdr lap))) - ;; Fetch the next op and its arg. - (setq op (car (car lap)) - arg (cdr (car lap))) - (setq lap (cdr lap)) - (indent-to indent) - (if (eq 'TAG op) - (progn - ;; We have a label. Display it, but first its pc value. - (if pc-value - (insert (format "%d:" pc-value))) - (insert (int-to-string (car arg)))) - ;; We have an instruction. Display its pc value first. - (if pc-value - (insert (format "%d" pc-value))) - (indent-to (+ indent disassemble-column-1-indent)) - (if (and op - (string-match "^byte-" (setq opname (symbol-name op)))) - (setq opname (substring opname 5)) - (setq opname "")) - (if (eq op 'byte-constant2) - (insert " #### shouldn't have seen constant2 here!\n ")) - (insert opname) - (indent-to (+ indent disassemble-column-1-indent - disassemble-column-2-indent - -1)) - (insert " ") - (cond ((memq op byte-goto-ops) - (insert (int-to-string (nth 1 arg)))) - ((memq op '(byte-call byte-unbind - byte-listN byte-concatN byte-insertN)) - (insert (int-to-string arg))) - ((memq op '(byte-varref byte-varset byte-varbind)) - (prin1 (car arg) (current-buffer))) - ((memq op '(byte-constant byte-constant2)) - ;; it's a constant - (setq arg (car arg)) - ;; but if the value of the constant is compiled code, then - ;; recursively disassemble it. - (cond ((or (compiled-function-p arg) - (and (eq (car-safe arg) 'lambda) - (assq 'byte-code arg)) - (and (eq (car-safe arg) 'macro) - (or (compiled-function-p (cdr arg)) - (and (eq (car-safe (cdr arg)) 'lambda) - (assq 'byte-code (cdr arg)))))) - (cond ((compiled-function-p arg) - (insert "\n")) - ((eq (car-safe arg) 'lambda) - (insert "")) - (t (insert "\n"))) - (disassemble-internal - arg - (+ indent disassemble-recursive-indent 1) - nil)) - ((eq (car-safe arg) 'byte-code) - (insert "\n") - (disassemble-1 ;recurse on byte-code object - arg - (+ indent disassemble-recursive-indent))) - ((eq (car-safe (car-safe arg)) 'byte-code) - (insert "(...)\n") - (mapcar ;recurse on list of byte-code objects - '(lambda (obj) - (disassemble-1 - obj - (+ indent disassemble-recursive-indent))) - arg)) - (t - ;; really just a constant - (let ((print-escape-newlines t)) - (prin1 arg (current-buffer)))))) - ) - (insert "\n"))))) - nil) - -(provide 'disass) - -;;; disass.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/auto-autoloads.el --- a/lisp/cc-mode/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,145 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'cc-mode-autoloads) (error "Already loaded")) - -;;;### (autoloads nil "cc-langs" "cc-mode/cc-langs.el") - -(defvar c-mode-syntax-table nil "\ -Syntax table used in c-mode buffers.") - -(defvar c++-mode-syntax-table nil "\ -Syntax table used in c++-mode buffers.") - -(defvar objc-mode-syntax-table nil "\ -Syntax table used in objc-mode buffers.") - -(defvar java-mode-syntax-table nil "\ -Syntax table used in java-mode buffers.") - -(defvar idl-mode-syntax-table nil "\ -Syntax table used in idl-mode buffers.") - -;;;*** - -;;;### (autoloads (idl-mode java-mode objc-mode c++-mode c-mode c-initialize-cc-mode) "cc-mode" "cc-mode/cc-mode.el") - -(autoload 'c-initialize-cc-mode "cc-mode" nil nil nil) - -(autoload 'c-mode "cc-mode" "\ -Major mode for editing K&R and ANSI C code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -c-mode buffer. This automatically sets up a mail buffer with version -information already added. You just need to add a description of the -problem, including a reproducible test case and send the message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `c-mode-hook' is run with no args, if that value is -bound and has a non-nil value. Also the hook `c-mode-common-hook' is -run first. - -Key bindings: -\\{c-mode-map}" t nil) - -(autoload 'c++-mode "cc-mode" "\ -Major mode for editing C++ code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -c++-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case, and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `c++-mode-hook' is run with no args, if that -variable is bound and has a non-nil value. Also the hook -`c-mode-common-hook' is run first. - -Key bindings: -\\{c++-mode-map}" t nil) - -(autoload 'objc-mode "cc-mode" "\ -Major mode for editing Objective C code. -To submit a problem report, enter `\\[c-submit-bug-report]' from an -objc-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case, and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `objc-mode-hook' is run with no args, if that value -is bound and has a non-nil value. Also the hook `c-mode-common-hook' -is run first. - -Key bindings: -\\{objc-mode-map}" t nil) - -(autoload 'java-mode "cc-mode" "\ -Major mode for editing Java code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -java-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `java-mode-hook' is run with no args, if that value -is bound and has a non-nil value. Also the common hook -`c-mode-common-hook' is run first. Note that this mode automatically -sets the \"java\" style before calling any hooks so be careful if you -set styles in `c-mode-common-hook'. - -Key bindings: -\\{java-mode-map}" t nil) - -(autoload 'idl-mode "cc-mode" "\ -Major mode for editing CORBA's IDL code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -idl-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case, and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `idl-mode-hook' is run with no args, if that -variable is bound and has a non-nil value. Also the hook -`c-mode-common-hook' is run first. - -Key bindings: -\\{idl-mode-map}" t nil) - -;;;*** - -;;;### (autoloads (c-set-offset c-add-style c-set-style) "cc-styles" "cc-mode/cc-styles.el") - -(autoload 'c-set-style "cc-styles" "\ -Set CC Mode variables to use one of several different indentation styles. -STYLENAME is a string representing the desired style from the list of -styles described in the variable `c-style-alist'. See that variable -for details of setting up styles. - -The variable `c-indentation-style' always contains the buffer's current -style name." t nil) - -(autoload 'c-add-style "cc-styles" "\ -Adds a style to `c-style-alist', or updates an existing one. -STYLE is a string identifying the style to add or update. DESCRIP is -an association list describing the style and must be of the form: - - ([BASESTYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) - -See the variable `c-style-alist' for the semantics of BASESTYLE, -VARIABLE and VALUE. This function also sets the current style to -STYLE using `c-set-style' if the optional SET-P flag is non-nil." t nil) - -(autoload 'c-set-offset "cc-styles" "\ -Change the value of a syntactic element symbol in `c-offsets-alist'. -SYMBOL is the syntactic element symbol to change and OFFSET is the new -offset for that syntactic element. Optional ADD says to add SYMBOL to -`c-offsets-alist' if it doesn't already appear there." t nil) - -;;;*** - -(provide 'cc-mode-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-align.el --- a/lisp/cc-mode/cc-align.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,393 +0,0 @@ -;;; cc-align.el --- custom indentation functions for CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -(eval-when-compile - (require 'cc-defs) - (require 'cc-vars) - (require 'cc-engine) - (require 'cc-langs)) - - -;; Standard indentation line-ups -(defun c-lineup-arglist (langelem) - ;; lineup the current arglist line with the arglist appearing just - ;; after the containing paren which starts the arglist. - (save-excursion - (let* ((containing-sexp - (save-excursion - ;; arglist-cont-nonempty gives relpos == - ;; to boi of containing-sexp paren. This - ;; is good when offset is +, but bad - ;; when it is c-lineup-arglist, so we - ;; have to special case a kludge here. - (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty)) - (progn - (beginning-of-line) - (backward-up-list 1) - (skip-chars-forward " \t" (c-point 'eol))) - (goto-char (cdr langelem))) - (point))) - (langelem-col (c-langelem-col langelem t))) - (if (save-excursion - (beginning-of-line) - (looking-at "[ \t]*)")) - (progn (goto-char (match-end 0)) - (forward-sexp -1) - (forward-char 1) - (c-forward-syntactic-ws) - (- (current-column) langelem-col)) - (goto-char containing-sexp) - (or (eolp) - (not (memq (char-after) '(?{ ?\( ))) - (let ((eol (c-point 'eol)) - (here (progn - (forward-char 1) - (skip-chars-forward " \t") - (point)))) - (c-forward-syntactic-ws) - (if (< (point) eol) - (goto-char here)))) - (- (current-column) langelem-col) - )))) - -(defun c-lineup-arglist-intro-after-paren (langelem) - ;; lineup an arglist-intro line to just after the open paren - (save-excursion - (let ((langelem-col (c-langelem-col langelem t)) - (ce-curcol (save-excursion - (beginning-of-line) - (backward-up-list 1) - (skip-chars-forward " \t" (c-point 'eol)) - (current-column)))) - (- ce-curcol langelem-col -1)))) - -(defun c-lineup-arglist-close-under-paren (langelem) - ;; lineup an arglist-intro line to just after the open paren - (save-excursion - (let ((langelem-col (c-langelem-col langelem t)) - (ce-curcol (save-excursion - (beginning-of-line) - (backward-up-list 1) - (current-column)))) - (- ce-curcol langelem-col)))) - -(defun c-lineup-streamop (langelem) - ;; lineup stream operators - (save-excursion - (let ((langelem-col (c-langelem-col langelem))) - (re-search-forward "<<\\|>>" (c-point 'eol) 'move) - (goto-char (match-beginning 0)) - (- (current-column) langelem-col)))) - -(defun c-lineup-multi-inher (langelem) - ;; line up multiple inheritance lines - (save-excursion - (let ((eol (c-point 'eol)) - (here (point)) - (langelem-col (c-langelem-col langelem))) - (skip-chars-forward "^:" eol) - (skip-chars-forward " \t:" eol) - (if (or (eolp) - (looking-at c-comment-start-regexp)) - (c-forward-syntactic-ws here)) - (- (current-column) langelem-col) - ))) - -(defun c-lineup-java-inher (langelem) - ;; line up Java implements and extends continuations - (save-excursion - (let ((langelem-col (c-langelem-col langelem))) - (forward-word 1) - (if (looking-at "[ \t]*$") - langelem-col - (c-forward-syntactic-ws) - (- (current-column) langelem-col))))) - -(defun c-lineup-java-throws (langelem) - ;; lineup func-decl-cont's in Java which are continuations of throws - ;; declarations. If `throws' starts the previous line, line up to - ;; just after that keyword. If not, lineup under the previous line. - (save-excursion - (let ((iopl (c-point 'iopl)) - (langelem-col (c-langelem-col langelem t)) - (extra 0)) - (back-to-indentation) - (cond - ((looking-at "throws[ \t\n]") - (goto-char (cdr langelem)) - (setq extra c-basic-offset)) - ((and (goto-char iopl) - (looking-at "throws[ \t\n]")) - (forward-word 1) - (skip-chars-forward " \t") - (if (eolp) - (progn - (back-to-indentation) - (setq extra c-basic-offset)))) - (t (goto-char iopl))) - (+ (- (current-column) langelem-col) extra)))) - -(defun c-lineup-C-comments (langelem) - ;; line up C block comment continuation lines - (save-excursion - (let ((here (point)) - (stars (progn (back-to-indentation) - (skip-chars-forward "*"))) - (langelem-col (c-langelem-col langelem))) - (back-to-indentation) - (if (not (re-search-forward "/\\([*]+\\)" (c-point 'eol) t)) - (progn - (if (not (looking-at "[*]+")) - (progn - ;; we now have to figure out where this comment begins. - (goto-char here) - (back-to-indentation) - (if (looking-at "[*]+/") - (progn (goto-char (match-end 0)) - (forward-comment -1)) - (goto-char (cdr langelem)) - (back-to-indentation)))) - (- (current-column) langelem-col)) - (if (zerop stars) - (progn - (skip-chars-forward " \t") - (- (current-column) langelem-col)) - ;; how many stars on comment opening line? if greater than - ;; on current line, align left. if less than or equal, - ;; align right. this should also pick up Javadoc style - ;; comments. - (if (> (length (match-string 1)) stars) - (progn - (back-to-indentation) - (- (current-column) -1 langelem-col)) - (- (current-column) stars langelem-col)) - ))))) - -(defun c-lineup-comment (langelem) - ;; support old behavior for comment indentation. we look at - ;; c-comment-only-line-offset to decide how to indent comment - ;; only-lines - (save-excursion - (back-to-indentation) - ;; this highly kludgiforous flag prevents the mapcar over - ;; c-syntactic-context from entering an infinite loop - (let ((recurse-prevention-flag (boundp 'recurse-prevention-flag))) - (cond - ;; CASE 1: preserve comment-column - (recurse-prevention-flag 0) - ((= (current-column) comment-column) - ;; we have to subtract out all other indentation - (- comment-column (apply '+ (mapcar 'c-get-offset - c-syntactic-context)))) - ;; indent as specified by c-comment-only-line-offset - ((not (bolp)) - (or (car-safe c-comment-only-line-offset) - c-comment-only-line-offset)) - (t - (or (cdr-safe c-comment-only-line-offset) - (car-safe c-comment-only-line-offset) - -1000)) ;jam it against the left side - )))) - -(defun c-lineup-runin-statements (langelem) - ;; line up statements in coding standards which place the first - ;; statement on the same line as the block opening brace. - (if (eq (char-after (cdr langelem)) ?{) - (save-excursion - (let ((langelem-col (c-langelem-col langelem))) - (forward-char 1) - (skip-chars-forward " \t") - (- (current-column) langelem-col))) - 0)) - -(defun c-lineup-math (langelem) - ;; line up math statement-cont after the equals - (save-excursion - (let ((equalp (save-excursion - (goto-char (c-point 'boi)) - (skip-chars-forward "^=" (c-point 'eol)) - (and (eq (char-after) ?=) - (- (point) (c-point 'boi))))) - (langelem-col (c-langelem-col langelem)) - donep) - (while (and (not donep) - (< (point) (c-point 'eol))) - (skip-chars-forward "^=" (c-point 'eol)) - (if (c-in-literal (cdr langelem)) - (forward-char 1) - (setq donep t))) - (if (not (eq (char-after) ?=)) - ;; there's no equal sign on the line - c-basic-offset - ;; calculate indentation column after equals and ws, unless - ;; our line contains an equals sign - (if (not equalp) - (progn - (forward-char 1) - (skip-chars-forward " \t") - (setq equalp 0))) - (- (current-column) equalp langelem-col)) - ))) - -(defun c-lineup-ObjC-method-call (langelem) - ;; Line up methods args as elisp-mode does with function args: go to - ;; the position right after the message receiver, and if you are at - ;; (eolp) indent the current line by a constant offset from the - ;; opening bracket; otherwise we are looking at the first character - ;; of the first method call argument, so lineup the current line - ;; with it. - (save-excursion - (let* ((extra (save-excursion - (back-to-indentation) - (c-backward-syntactic-ws (cdr langelem)) - (if (eq (char-before) ?:) - (- c-basic-offset) - 0))) - (open-bracket-pos (cdr langelem)) - (open-bracket-col (progn - (goto-char open-bracket-pos) - (current-column))) - (target-col (progn - (forward-char) - (forward-sexp) - (skip-chars-forward " \t") - (if (eolp) - (+ open-bracket-col c-basic-offset) - (current-column)))) - ) - (- target-col open-bracket-col extra)))) - -(defun c-lineup-ObjC-method-args (langelem) - ;; Line up the colons that separate args. This is done trying to - ;; align colons vertically. - (save-excursion - (let* ((here (c-point 'boi)) - (curcol (progn (goto-char here) (current-column))) - (eol (c-point 'eol)) - (relpos (cdr langelem)) - (first-col-column (progn - (goto-char relpos) - (skip-chars-forward "^:" eol) - (and (eq (char-after) ?:) - (current-column))))) - (if (not first-col-column) - c-basic-offset - (goto-char here) - (skip-chars-forward "^:" eol) - (if (eq (char-after) ?:) - (+ curcol (- first-col-column (current-column))) - c-basic-offset))))) - -(defun c-lineup-ObjC-method-args-2 (langelem) - ;; Line up the colons that separate args. This is done trying to - ;; align the colon on the current line with the previous one. - (save-excursion - (let* ((here (c-point 'boi)) - (curcol (progn (goto-char here) (current-column))) - (eol (c-point 'eol)) - (relpos (cdr langelem)) - (prev-col-column (progn - (skip-chars-backward "^:" relpos) - (and (eq (char-before) ?:) - (- (current-column) 1))))) - (if (not prev-col-column) - c-basic-offset - (goto-char here) - (skip-chars-forward "^:" eol) - (if (eq (char-after) ?:) - (+ curcol (- prev-col-column (current-column))) - c-basic-offset))))) - -(defun c-snug-do-while (syntax pos) - "Dynamically calculate brace hanginess for do-while statements. -Using this function, `while' clauses that end a `do-while' block will -remain on the same line as the brace that closes that block. - -See `c-hanging-braces-alist' for how to utilize this function as an -ACTION associated with `block-close' syntax." - (save-excursion - (let (langelem) - (if (and (eq syntax 'block-close) - (setq langelem (assq 'block-close c-syntactic-context)) - (progn (goto-char (cdr langelem)) - (if (eq (char-after) ?{) - (c-safe (forward-sexp -1))) - (looking-at "\\[^_]"))) - '(before) - '(before after))))) - -(defun c-gnu-impose-minimum () - "Imposes a minimum indentation for lines inside a top-level construct. -The variable `c-label-minimum-indentation' specifies the minimum -indentation amount." - (let ((non-top-levels '(defun-block-intro statement statement-cont - statement-block-intro statement-case-intro - statement-case-open substatement substatement-open - case-label label do-while-closure else-clause - )) - (syntax c-syntactic-context) - langelem) - (while syntax - (setq langelem (car (car syntax)) - syntax (cdr syntax)) - ;; don't adjust comment-only lines - (cond ((eq langelem 'comment-intro) - (setq syntax nil)) - ((memq langelem non-top-levels) - (save-excursion - (setq syntax nil) - (back-to-indentation) - (if (zerop (current-column)) - (insert (make-string c-label-minimum-indentation 32))) - )) - )))) - - -;; Useful for c-hanging-semi&comma-criteria -(defun c-semi&comma-inside-parenlist () - "Determine if a newline should be added after a semicolon. -If a comma was inserted, no determination is made. If a semicolon was -inserted inside a parenthesis list, no newline is added otherwise a -newline is added. In either case, checking is stopped. This supports -exactly the old newline insertion behavior." - ;; newline only after semicolon, but only if that semicolon is not - ;; inside a parenthesis list (e.g. a for loop statement) - (if (not (eq last-command-char ?\;)) - nil ; continue checking - (if (condition-case nil - (save-excursion - (up-list -1) - (not (eq (char-after) ?\())) - (error t)) - t - 'stop))) - - -(provide 'cc-align) -;;; cc-align.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-cmds.el --- a/lisp/cc-mode/cc-cmds.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1444 +0,0 @@ -;;; cc-cmds.el --- user level commands for CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -(eval-when-compile - (require 'cc-defs)) - - -(defun c-calculate-state (arg prevstate) - ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If - ;; arg is nil or zero, toggle the state. If arg is negative, turn - ;; the state off, and if arg is positive, turn the state on - (if (or (not arg) - (zerop (setq arg (prefix-numeric-value arg)))) - (not prevstate) - (> arg 0))) - -;; Auto-newline and hungry-delete -(defun c-toggle-auto-state (arg) - "Toggle auto-newline feature. -Optional numeric ARG, if supplied turns on auto-newline when positive, -turns it off when negative, and just toggles it when zero. - -When the auto-newline feature is enabled (as evidenced by the `/a' or -`/ah' on the modeline after the mode name) newlines are automatically -inserted after special characters such as brace, comma, semi-colon, -and colon." - (interactive "P") - (setq c-auto-newline (c-calculate-state arg c-auto-newline)) - (c-update-modeline) - (c-keep-region-active)) - -(defun c-toggle-hungry-state (arg) - "Toggle hungry-delete-key feature. -Optional numeric ARG, if supplied turns on hungry-delete when positive, -turns it off when negative, and just toggles it when zero. - -When the hungry-delete-key feature is enabled (as evidenced by the -`/h' or `/ah' on the modeline after the mode name) the delete key -gobbles all preceding whitespace in one fell swoop." - (interactive "P") - (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key)) - (c-update-modeline) - (c-keep-region-active)) - -(defun c-toggle-auto-hungry-state (arg) - "Toggle auto-newline and hungry-delete-key features. -Optional numeric ARG, if supplied turns on auto-newline and -hungry-delete when positive, turns them off when negative, and just -toggles them when zero. - -See `c-toggle-auto-state' and `c-toggle-hungry-state' for details." - (interactive "P") - (setq c-auto-newline (c-calculate-state arg c-auto-newline)) - (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key)) - (c-update-modeline) - (c-keep-region-active)) - - -;; Electric keys - -;; Note: In XEmacs 20.3 the Delete and BackSpace keysyms have been -;; separated and "\177" is no longer an alias for both keys. Also, -;; the variable delete-key-deletes-forward controls in which direction -;; the Delete keysym deletes characters. The functions -;; c-electric-delete and c-electric-backspace attempt to deal with -;; this new functionality. For Emacs 19 and XEmacs 19 backwards -;; compatibility, the old behavior has moved to c-electric-backspace -;; and c-backspace-function. - -(defun c-electric-backspace (arg) - "Deletes preceding character or whitespace. -If `c-hungry-delete-key' is non-nil, as evidenced by the \"/h\" or -\"/ah\" string on the mode line, then all preceding whitespace is -consumed. If however an ARG is supplied, or `c-hungry-delete-key' is -nil, or point is inside a literal then the function in the variable -`c-backspace-function' is called. - -See also \\[c-electric-delete]." - (interactive "P") - (if (or (not c-hungry-delete-key) - arg - (c-in-literal)) - (funcall c-backspace-function (prefix-numeric-value arg)) - (let ((here (point))) - (skip-chars-backward " \t\n") - (if (/= (point) here) - (delete-region (point) here) - (funcall c-backspace-function 1) - )))) - -(defun c-electric-delete (arg) - "Deletes preceding or following character or whitespace. - -The behavior of this function depends on the variable -`delete-key-deletes-forward'. If this variable is nil (or does not -exist, as in older Emacsen), then this function behaves identical to -\\[c-electric-backspace]. - -If `delete-key-deletes-forward' is non-nil, then deletion occurs in -the forward direction. So if `c-hungry-delete-key' is non-nil, as -evidenced by the \"/h\" or \"/ah\" string on the mode line, then all -following whitespace is consumed. If however an ARG is supplied, or -`c-hungry-delete-key' is nil, or point is inside a literal then the -function in the variable `c-delete-function' is called." - (interactive "P") - (if (and (boundp 'delete-key-deletes-forward) - delete-key-deletes-forward) - (if (or (not c-hungry-delete-key) - arg - (c-in-literal)) - (funcall c-delete-function (prefix-numeric-value arg)) - (let ((here (point))) - (skip-chars-forward " \t\n") - (if (/= (point) here) - (delete-region (point) here) - (funcall c-delete-function 1)))) - ;; act just like c-electric-backspace - (c-electric-backspace arg))) - -(defun c-electric-pound (arg) - "Electric pound (`#') insertion. -Inserts a `#' character specially depending on the variable -`c-electric-pound-behavior'. If a numeric ARG is supplied, or if -point is inside a literal, nothing special happens." - (interactive "P") - (if (or (c-in-literal) - arg - (not (memq 'alignleft c-electric-pound-behavior))) - ;; do nothing special - (self-insert-command (prefix-numeric-value arg)) - ;; place the pound character at the left edge - (let ((pos (- (point-max) (point))) - (bolp (bolp))) - (beginning-of-line) - (delete-horizontal-space) - (insert-char last-command-char 1) - (and (not bolp) - (goto-char (- (point-max) pos))) - ))) - -(defun c-electric-brace (arg) - "Insert a brace. - -If the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, newlines are inserted before and -after braces based on the value of `c-hanging-braces-alist'. - -Also, the line is re-indented unless a numeric ARG is supplied, there -are non-whitespace characters present on the line after the brace, or -the brace is inserted inside a literal." - (interactive "P") - (let* ((c-state-cache (c-parse-state)) - (safepos (c-safe-position (point) c-state-cache)) - (literal (c-in-literal safepos))) - ;; if we're in a literal, or we're not at the end of the line, or - ;; a numeric arg is provided, or auto-newlining is turned off, - ;; then just insert the character. - (if (or literal arg -; (not c-auto-newline) - (not (looking-at "[ \t]*$"))) - (self-insert-command (prefix-numeric-value arg)) - (let* ((syms '(class-open class-close defun-open defun-close - inline-open inline-close brace-list-open brace-list-close - brace-list-intro brace-list-entry block-open block-close - substatement-open statement-case-open - extern-lang-open extern-lang-close)) - ;; we want to inhibit blinking the paren since this will - ;; be most disruptive. we'll blink it ourselves later on - (old-blink-paren blink-paren-function) - blink-paren-function - (insertion-point (point)) - delete-temp-newline - (preserve-p (and (not (bobp)) - (eq ?\ (char-syntax (char-before))))) - ;; shut this up too - (c-echo-syntactic-information-p nil) - (syntax (progn - ;; only insert a newline if there is - ;; non-whitespace behind us - (if (save-excursion - (skip-chars-backward " \t") - (not (bolp))) - (progn (newline) - (setq delete-temp-newline t))) - (self-insert-command (prefix-numeric-value arg)) - ;; state cache doesn't change - (c-guess-basic-syntax))) - (newlines (and - c-auto-newline - (or (c-lookup-lists syms syntax c-hanging-braces-alist) - '(ignore before after))))) - ;; If syntax is a function symbol, then call it using the - ;; defined semantics. - (if (and (not (consp (cdr newlines))) - (functionp (cdr newlines))) - (let ((c-syntactic-context syntax)) - (setq newlines - (funcall (cdr newlines) (car newlines) insertion-point)))) - ;; does a newline go before the open brace? - (if (memq 'before newlines) - ;; we leave the newline we've put in there before, - ;; but we need to re-indent the line above - (let ((pos (- (point-max) (point))) - (here (point)) - (c-state-cache c-state-cache)) - (forward-line -1) - ;; we may need to update the cache. this should still be - ;; faster than recalculating the state in many cases - (save-excursion - (save-restriction - (narrow-to-region here (point)) - (if (and (c-safe (progn (backward-up-list -1) t)) - (memq (char-before) '(?\) ?})) - (progn (widen) - (c-safe (progn (forward-sexp -1) t)))) - (setq c-state-cache - (c-hack-state (point) 'open c-state-cache)) - (if (and (car c-state-cache) - (not (consp (car c-state-cache))) - (<= (point) (car c-state-cache))) - (setq c-state-cache (cdr c-state-cache)) - )))) - (let ((here (point)) - (shift (c-indent-line))) - (setq c-state-cache (c-adjust-state (c-point 'bol) here - (- shift) c-state-cache))) - (goto-char (- (point-max) pos)) - ;; if the buffer has changed due to the indentation, we - ;; need to recalculate syntax for the current line, but - ;; we won't need to update the state cache. - (if (/= (point) here) - (setq syntax (c-guess-basic-syntax)))) - ;; must remove the newline we just stuck in (if we really did it) - (and delete-temp-newline - (save-excursion - ;; if there is whitespace before point, then preserve - ;; at least one space. - (delete-indentation) - (just-one-space) - (if (not preserve-p) - (delete-char -1)))) - ;; since we're hanging the brace, we need to recalculate - ;; syntax. Update the state to accurately reflect the - ;; beginning of the line. We punt if we cross any open or - ;; closed parens because its just too hard to modify the - ;; known state. This limitation will be fixed in v5. - (save-excursion - (let ((bol (c-point 'bol))) - (if (zerop (car (parse-partial-sexp bol (1- (point))))) - (setq c-state-cache (c-whack-state bol c-state-cache) - syntax (c-guess-basic-syntax)) - ;; gotta punt. this requires some horrible kludgery - (beginning-of-line) - (makunbound 'c-state-cache) - (setq c-state-cache (c-parse-state) - syntax nil)))) - ) - ;; now adjust the line's indentation. don't update the state - ;; cache since c-guess-basic-syntax isn't called when the - ;; syntax is passed to c-indent-line - (let ((here (point)) - (shift (c-indent-line syntax))) - (setq c-state-cache (c-adjust-state (c-point 'bol) here - (- shift) c-state-cache))) - ;; Do all appropriate clean ups - (let ((here (point)) - (pos (- (point-max) (point))) - mbeg mend) - ;; clean up empty defun braces - (if (and c-auto-newline - (memq 'empty-defun-braces c-cleanup-list) - (eq last-command-char ?\}) - (c-intersect-lists '(defun-close class-close inline-close) - syntax) - (progn - (forward-char -1) - (skip-chars-backward " \t\n") - (eq (char-before) ?\{)) - ;; make sure matching open brace isn't in a comment - (not (c-in-literal))) - (delete-region (point) (1- here))) - ;; clean up brace-else-brace - (if (and c-auto-newline - (memq 'brace-else-brace c-cleanup-list) - (eq last-command-char ?\{) - (re-search-backward "}[ \t\n]*else[ \t\n]*{" nil t) - (progn - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= mend here)) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert "} else {"))) - ;; clean up brace-elseif-brace - (if (and c-auto-newline - (memq 'brace-elseif-brace c-cleanup-list) - (eq last-command-char ?\{) - (re-search-backward "}[ \t\n]*else[ \t\n]+if[ \t\n]*" nil t) - (save-excursion - (goto-char (match-end 0)) - (c-safe (forward-sexp 1)) - (skip-chars-forward " \t\n") - (setq mbeg (match-beginning 0) - mend (match-end 0)) - (= here (1+ (point)))) - (not (c-in-literal))) - (progn - (delete-region mbeg mend) - (insert "} else if "))) - (goto-char (- (point-max) pos)) - ) - ;; does a newline go after the brace? - (if (memq 'after newlines) - (progn - (newline) - ;; update on c-state-cache - (let* ((bufpos (- (point) 2)) - (which (if (eq (char-after bufpos) ?{) 'open 'close)) - (c-state-cache (c-hack-state bufpos which c-state-cache))) - (c-indent-line)))) - ;; blink the paren - (and (eq last-command-char ?\}) - old-blink-paren - (save-excursion - (c-backward-syntactic-ws safepos) - (funcall old-blink-paren))) - )))) - -(defun c-electric-slash (arg) - "Insert a slash character. - -Indent the line as a comment, if: - - 1. The slash is second of a `//' line oriented comment introducing - token and we are on a comment-only-line, or - - 2. The slash is part of a `*/' token that closes a block oriented - comment. - -If numeric ARG is supplied or point is inside a literal, indentation -is inhibited." - (interactive "P") - (let* ((ch (char-before)) - (indentp (and (not arg) - (eq last-command-char ?/) - (or (and (eq ch ?/) - (not (c-in-literal))) - (and (eq ch ?*) - (c-in-literal))) - )) - ;; shut this up - (c-echo-syntactic-information-p nil)) - (self-insert-command (prefix-numeric-value arg)) - (if indentp - (c-indent-line)))) - -(defun c-electric-star (arg) - "Insert a star character. -If the star is the second character of a C style comment introducing -construct, and we are on a comment-only-line, indent line as comment. -If numeric ARG is supplied or point is inside a literal, indentation -is inhibited." - (interactive "P") - (self-insert-command (prefix-numeric-value arg)) - ;; if we are in a literal, or if arg is given do not re-indent the - ;; current line, unless this star introduces a comment-only line. - (if (and (not arg) - (memq (c-in-literal) '(c)) - (eq (char-before) ?*) - (save-excursion - (forward-char -1) - (skip-chars-backward "*") - (if (eq (char-before) ?/) - (forward-char -1)) - (skip-chars-backward " \t") - (bolp))) - ;; shut this up - (let (c-echo-syntactic-information-p) - (c-indent-line)) - )) - -(defun c-electric-semi&comma (arg) - "Insert a comma or semicolon. -When the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, a newline might be inserted. See -the variable `c-hanging-semi&comma-criteria' for how newline insertion -is determined. - -When semicolon is inserted, the line is re-indented unless a numeric -arg is supplied, point is inside a literal, or there are -non-whitespace characters on the line following the semicolon." - (interactive "P") - (let* ((lim (c-most-enclosing-brace (c-parse-state))) - (literal (c-in-literal lim)) - (here (point)) - ;; shut this up - (c-echo-syntactic-information-p nil)) - (if (or literal - arg - (not (looking-at "[ \t]*$"))) - (self-insert-command (prefix-numeric-value arg)) - ;; do some special stuff with the character - (self-insert-command (prefix-numeric-value arg)) - ;; do all cleanups, reindentations, and newline insertions, but - ;; only if c-auto-newline is turned on - (if (not c-auto-newline) nil - ;; clean ups - (let ((pos (- (point-max) (point)))) - (if (and (or (and - (eq last-command-char ?,) - (memq 'list-close-comma c-cleanup-list)) - (and - (eq last-command-char ?\;) - (memq 'defun-close-semi c-cleanup-list))) - (progn - (forward-char -1) - (skip-chars-backward " \t\n") - (eq (char-before) ?})) - ;; make sure matching open brace isn't in a comment - (not (c-in-literal lim))) - (delete-region (point) here)) - (goto-char (- (point-max) pos))) - ;; re-indent line - (c-indent-line) - ;; check to see if a newline should be added - (let ((criteria c-hanging-semi&comma-criteria) - answer add-newline-p) - (while criteria - (setq answer (funcall (car criteria))) - ;; only nil value means continue checking - (if (not answer) - (setq criteria (cdr criteria)) - (setq criteria nil) - ;; only 'stop specifically says do not add a newline - (setq add-newline-p (not (eq answer 'stop))) - )) - (if add-newline-p - (progn (newline) - (c-indent-line))) - ))))) - -(defun c-electric-colon (arg) - "Insert a colon. - -If the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, newlines are inserted before and -after colons based on the value of `c-hanging-colons-alist'. - -Also, the line is re-indented unless a numeric ARG is supplied, there -are non-whitespace characters present on the line after the colon, or -the colon is inserted inside a literal. - -This function cleans up double colon scope operators based on the -value of `c-cleanup-list'." - (interactive "P") - (let* ((bod (c-point 'bod)) - (literal (c-in-literal bod)) - syntax newlines - ;; shut this up - (c-echo-syntactic-information-p nil)) - (if (or literal - arg - (not (looking-at "[ \t]*$"))) - (self-insert-command (prefix-numeric-value arg)) - ;; insert the colon, then do any specified cleanups - (self-insert-command (prefix-numeric-value arg)) - (let ((pos (- (point-max) (point))) - (here (point))) - (if (and c-auto-newline - (memq 'scope-operator c-cleanup-list) - (eq (char-before) ?:) - (progn - (forward-char -1) - (skip-chars-backward " \t\n") - (eq (char-before) ?:)) - (not (c-in-literal)) - (not (eq (char-after (- (point) 2)) ?:))) - (delete-region (point) (1- here))) - (goto-char (- (point-max) pos))) - ;; lets do some special stuff with the colon character - (setq syntax (c-guess-basic-syntax) - ;; some language elements can only be determined by - ;; checking the following line. Lets first look for ones - ;; that can be found when looking on the line with the - ;; colon - newlines - (and c-auto-newline - (or (c-lookup-lists '(case-label label access-label) - syntax c-hanging-colons-alist) - (c-lookup-lists '(member-init-intro inher-intro) - (prog2 - (insert "\n") - (c-guess-basic-syntax) - (delete-char -1)) - c-hanging-colons-alist)))) - ;; indent the current line - (c-indent-line syntax) - ;; does a newline go before the colon? Watch out for already - ;; non-hung colons. However, we don't unhang them because that - ;; would be a cleanup (and anti-social). - (if (and (memq 'before newlines) - (save-excursion - (skip-chars-backward ": \t") - (not (bolp)))) - (let ((pos (- (point-max) (point)))) - (forward-char -1) - (newline) - (c-indent-line) - (goto-char (- (point-max) pos)))) - ;; does a newline go after the colon? - (if (memq 'after (cdr-safe newlines)) - (progn - (newline) - (c-indent-line))) - ))) - -(defun c-electric-lt-gt (arg) - "Insert a less-than, or greater-than character. -When the auto-newline feature is turned on, as evidenced by the \"/a\" -or \"/ah\" string on the mode line, the line will be re-indented if -the character inserted is the second of a C++ style stream operator -and the buffer is in C++ mode. - -The line will also not be re-indented if a numeric argument is -supplied, or point is inside a literal." - (interactive "P") - (let ((indentp (and (not arg) - (eq (char-before) last-command-char) - (not (c-in-literal)))) - ;; shut this up - (c-echo-syntactic-information-p nil)) - (self-insert-command (prefix-numeric-value arg)) - (if indentp - (c-indent-line)))) - - - -;; better movement routines for ThisStyleOfVariablesCommonInCPlusPlus -;; originally contributed by Terry_Glanfield.Southern@rxuk.xerox.com -(defun c-forward-into-nomenclature (&optional arg) - "Move forward to end of a nomenclature section or word. -With arg, to it arg times." - (interactive "p") - (let ((case-fold-search nil)) - (if (> arg 0) - (re-search-forward "\\W*\\([A-Z]*[a-z0-9]*\\)" (point-max) t arg) - (while (and (< arg 0) - (re-search-backward - "\\(\\(\\W\\|[a-z0-9]\\)[A-Z]+\\|\\W\\w+\\)" - (point-min) 0)) - (forward-char 1) - (setq arg (1+ arg))))) - (c-keep-region-active)) - -(defun c-backward-into-nomenclature (&optional arg) - "Move backward to beginning of a nomenclature section or word. -With optional ARG, move that many times. If ARG is negative, move -forward." - (interactive "p") - (c-forward-into-nomenclature (- arg)) - (c-keep-region-active)) - -(defun c-scope-operator () - "Insert a double colon scope operator at point. -No indentation or other \"electric\" behavior is performed." - (interactive) - (insert "::")) - - -(defun c-beginning-of-statement (&optional count lim sentence-flag) - "Go to the beginning of the innermost C statement. -With prefix arg, go back N - 1 statements. If already at the -beginning of a statement then go to the beginning of the preceding -one. If within a string or comment, or next to a comment (only -whitespace between), move by sentences instead of statements. - -When called from a program, this function takes 3 optional args: the -repetition count, a buffer position limit which is the farthest back -to search, and a flag saying whether to do sentence motion when in a -comment." - (interactive (list (prefix-numeric-value current-prefix-arg) - nil t)) - (let ((here (point)) - (count (or count 1)) - (lim (or lim (c-point 'bod))) - state) - (save-excursion - (goto-char lim) - (setq state (parse-partial-sexp (point) here nil nil))) - (if (and sentence-flag - (or (nth 3 state) - (nth 4 state) - ;; skipping forward into a comment? - (and (> 0 count) - (save-excursion - (skip-chars-forward " \t\n") - (or (eobp) - (looking-at comment-start-skip)))) - (and (< 0 count) - (save-excursion - (skip-chars-backward " \t\n") - (goto-char (- (point) 2)) - (looking-at "\\*/"))))) - (forward-sentence (- count)) - (while (> count 0) - (c-beginning-of-statement-1 lim) - (setq count (1- count))) - (while (< count 0) - (c-end-of-statement-1) - (setq count (1+ count)))) - ;; its possible we've been left up-buf of lim - (goto-char (max (point) lim)) - ) - (c-keep-region-active)) - -(defun c-end-of-statement (&optional count lim sentence-flag) - "Go to the end of the innermost C statement. - -With prefix arg, go forward N - 1 statements. Move forward to end of -the next statement if already at end. If within a string or comment, -move by sentences instead of statements. - -When called from a program, this function takes 3 optional args: the -repetition count, a buffer position limit which is the farthest back -to search, and a flag saying whether to do sentence motion when in a -comment." - (interactive (list (prefix-numeric-value current-prefix-arg) - nil t)) - (c-beginning-of-statement (- (or count 1)) lim sentence-flag) - (c-keep-region-active)) - - -;; set up electric character functions to work with pending-del, -;; (a.k.a. delsel) mode. All symbols get the t value except -;; the functions which delete, which gets 'supersede. -(mapcar - (function - (lambda (sym) - (put sym 'delete-selection t) ; for delsel (Emacs) - (put sym 'pending-delete t))) ; for pending-del (XEmacs) - '(c-electric-pound - c-electric-brace - c-electric-slash - c-electric-star - c-electric-semi&comma - c-electric-lt-gt - c-electric-colon)) -(put 'c-electric-delete 'delete-selection 'supersede) ; delsel -(put 'c-electric-delete 'pending-delete 'supersede) ; pending-del -(put 'c-electric-backspace 'delete-selection 'supersede) ; delsel -(put 'c-electric-backspace 'pending-delete 'supersede) ; pending-del - - -;; This is used by indent-for-comment to decide how much to indent a -;; comment in C code based on its context. -(defun c-comment-indent () - (if (looking-at (concat "^\\(" c-comment-start-regexp "\\)")) - 0 ;Existing comment at bol stays there. - (let ((opoint (point)) - placeholder) - (save-excursion - (beginning-of-line) - (cond - ;; CASE 1: A comment following a solitary close-brace should - ;; have only one space. - ((looking-at (concat "[ \t]*}[ \t]*\\($\\|" - c-comment-start-regexp - "\\)")) - (search-forward "}") - (1+ (current-column))) - ;; CASE 2: 2 spaces after #endif - ((or (looking-at "^#[ \t]*endif[ \t]*") - (looking-at "^#[ \t]*else[ \t]*")) - 7) - ;; CASE 3: when comment-column is nil, calculate the offset - ;; according to c-offsets-alist. E.g. identical to hitting - ;; TAB. - ((and c-indent-comments-syntactically-p - (save-excursion - (skip-chars-forward " \t") - (or (looking-at comment-start) - (eolp)))) - (let ((syntax (c-guess-basic-syntax))) - ;; BOGOSITY ALERT: if we're looking at the eol, its - ;; because indent-for-comment hasn't put the comment-start - ;; in the buffer yet. this will screw up the syntactic - ;; analysis so we kludge in the necessary info. Another - ;; kludge is that if we're at the bol, then we really want - ;; to ignore any anchoring as specified by - ;; c-comment-only-line-offset since it doesn't apply here. - (if (save-excursion - (beginning-of-line) - (skip-chars-forward " \t") - (eolp)) - (c-add-syntax 'comment-intro)) - (let ((c-comment-only-line-offset - (if (consp c-comment-only-line-offset) - c-comment-only-line-offset - (cons c-comment-only-line-offset - c-comment-only-line-offset)))) - (apply '+ (mapcar 'c-get-offset syntax))))) - ;; CASE 4: use comment-column if previous line is a - ;; comment-only line indented to the left of comment-column - ((save-excursion - (beginning-of-line) - (and (not (bobp)) - (forward-line -1)) - (skip-chars-forward " \t") - (prog1 - (looking-at c-comment-start-regexp) - (setq placeholder (point)))) - (goto-char placeholder) - (if (< (current-column) comment-column) - comment-column - (current-column))) - ;; CASE 5: If comment-column is 0, and nothing but space - ;; before the comment, align it at 0 rather than 1. - ((progn - (goto-char opoint) - (skip-chars-backward " \t") - (and (= comment-column 0) (bolp))) - 0) - ;; CASE 6: indent at comment column except leave at least one - ;; space. - (t (max (1+ (current-column)) - comment-column)) - ))))) - - -;; for proposed new variable comment-line-break-function -(defun c-comment-line-break-function (&optional soft) - ;; we currently don't do anything with soft line breaks - (let ((literal (c-in-literal)) - at-comment-col) - (cond - ((eq literal 'string)) - ((or (not c-comment-continuation-stars) - (not literal)) - (indent-new-comment-line soft)) - (t (let ((here (point)) - (leader c-comment-continuation-stars)) - (back-to-indentation) - ;; comment could be hanging - (if (not (c-in-literal)) - (progn - (forward-line 1) - (forward-comment -1) - (setq at-comment-col (= (current-column) comment-column)))) - ;; are we looking at a block or lines style comment? - (if (and (looking-at (concat "\\(" c-comment-start-regexp - "\\)[ \t]+")) - (string-equal (match-string 1) "//")) - ;; line style - (setq leader "// ")) - (goto-char here) - (delete-region (progn (skip-chars-backward " \t") (point)) - (progn (skip-chars-forward " \t") (point))) - (newline) - ;; to avoid having an anchored comment that c-indent-line will - ;; trip up on - (insert " " leader) - (if at-comment-col - (indent-for-comment)) - (c-indent-line)))))) - -;; advice for indent-new-comment-line for older Emacsen -(if (boundp 'comment-line-break-function) - nil - (require 'advice) - (defadvice indent-new-comment-line (around c-line-break-advice activate) - (if (or (not c-buffer-is-cc-mode) - (not (c-in-literal)) - (not c-comment-continuation-stars)) - ad-do-it - (c-comment-line-break-function (ad-get-arg 0))))) - -;; used by outline-minor-mode -(defun c-outline-level () - (save-excursion - (skip-chars-forward "\t ") - (current-column))) - - -(defun c-up-conditional (count) - "Move back to the containing preprocessor conditional, leaving mark behind. -A prefix argument acts as a repeat count. With a negative argument, -move forward to the end of the containing preprocessor conditional. -When going backwards, `#elif' is treated like `#else' followed by -`#if'. When going forwards, `#elif' is ignored." - (interactive "p") - (c-forward-conditional (- count) t) - (c-keep-region-active)) - -(defun c-backward-conditional (count &optional up-flag) - "Move back across a preprocessor conditional, leaving mark behind. -A prefix argument acts as a repeat count. With a negative argument, -move forward across a preprocessor conditional." - (interactive "p") - (c-forward-conditional (- count) up-flag) - (c-keep-region-active)) - -(defun c-forward-conditional (count &optional up-flag) - "Move forward across a preprocessor conditional, leaving mark behind. -A prefix argument acts as a repeat count. With a negative argument, -move backward across a preprocessor conditional." - (interactive "p") - (let* ((forward (> count 0)) - (increment (if forward -1 1)) - (search-function (if forward 're-search-forward 're-search-backward)) - (new)) - (save-excursion - (while (/= count 0) - (let ((depth (if up-flag 0 -1)) found) - (save-excursion - ;; Find the "next" significant line in the proper direction. - (while (and (not found) - ;; Rather than searching for a # sign that - ;; comes at the beginning of a line aside from - ;; whitespace, search first for a string - ;; starting with # sign. Then verify what - ;; precedes it. This is faster on account of - ;; the fastmap feature of the regexp matcher. - (funcall search-function - "#[ \t]*\\(if\\|elif\\|endif\\)" - nil t)) - (beginning-of-line) - ;; Now verify it is really a preproc line. - (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\)") - (let ((prev depth)) - ;; Update depth according to what we found. - (beginning-of-line) - (cond ((looking-at "[ \t]*#[ \t]*endif") - (setq depth (+ depth increment))) - ((looking-at "[ \t]*#[ \t]*elif") - (if (and forward (= depth 0)) - (setq found (point)))) - (t (setq depth (- depth increment)))) - ;; If we are trying to move across, and we find an - ;; end before we find a beginning, get an error. - (if (and (< prev 0) (< depth prev)) - (error (if forward - "No following conditional at this level" - "No previous conditional at this level"))) - ;; When searching forward, start from next line so - ;; that we don't find the same line again. - (if forward (forward-line 1)) - ;; If this line exits a level of conditional, exit - ;; inner loop. - (if (< depth 0) - (setq found (point)))) - ;; else - (if forward (forward-line 1)) - ))) - (or found - (error "No containing preprocessor conditional")) - (goto-char (setq new found))) - (setq count (+ count increment)))) - (push-mark) - (goto-char new)) - (c-keep-region-active)) - - -;; commands to indent lines, regions, defuns, and expressions -(defun c-indent-command (&optional whole-exp) - "Indent current line as C code, and/or insert some whitespace. - -If `c-tab-always-indent' is t, always just indent the current line. -If nil, indent the current line only if point is at the left margin or -in the line's indentation; otherwise insert some whitespace[*]. If -other than nil or t, then some whitespace[*] is inserted only within -literals (comments and strings) and inside preprocessor directives, -but the line is always reindented. - -A numeric argument, regardless of its value, means indent rigidly all -the lines of the expression starting after point so that this line -becomes properly indented. The relative indentation among the lines -of the expression are preserved. - - [*] The amount and kind of whitespace inserted is controlled by the - variable `c-insert-tab-function', which is called to do the actual - insertion of whitespace. Normally the function in this variable - just inserts a tab character, or the equivalent number of spaces, - depending on the variable `indent-tabs-mode'." - - (interactive "P") - (let ((bod (c-point 'bod))) - (if whole-exp - ;; If arg, always indent this line as C - ;; and shift remaining lines of expression the same amount. - (let ((shift-amt (c-indent-line)) - beg end) - (save-excursion - (if (eq c-tab-always-indent t) - (beginning-of-line)) - (setq beg (point)) - (forward-sexp 1) - (setq end (point)) - (goto-char beg) - (forward-line 1) - (setq beg (point))) - (if (> end beg) - (indent-code-rigidly beg end (- shift-amt) "#"))) - ;; No arg supplied, use c-tab-always-indent to determine - ;; behavior - (cond - ;; CASE 1: indent when at column zero or in lines indentation, - ;; otherwise insert a tab - ((not c-tab-always-indent) - (if (save-excursion - (skip-chars-backward " \t") - (not (bolp))) - (funcall c-insert-tab-function) - (c-indent-line))) - ;; CASE 2: just indent the line - ((eq c-tab-always-indent t) - (c-indent-line)) - ;; CASE 3: if in a literal, insert a tab, but always indent the - ;; line - (t - (if (c-in-literal bod) - (funcall c-insert-tab-function)) - (c-indent-line) - ))))) - -(defun c-indent-exp (&optional shutup-p) - "Indent each line in balanced expression following point. -Optional SHUTUP-P if non-nil, inhibits message printing and error checking." - (interactive "P") - (let ((here (point)) - end progress-p) - (unwind-protect - (let ((c-echo-syntactic-information-p nil) ;keep quiet for speed - (start (progn - ;; try to be smarter about finding the range of - ;; lines to indent. skip all following - ;; whitespace. failing that, try to find any - ;; opening brace on the current line - (skip-chars-forward " \t\n") - (if (memq (char-after) '(?\( ?\[ ?\{)) - (point) - (let ((state (parse-partial-sexp (point) - (c-point 'eol)))) - (and (nth 1 state) - (goto-char (nth 1 state)) - (memq (char-after) '(?\( ?\[ ?\{)) - (point))))))) - ;; find balanced expression end - (setq end (and (c-safe (progn (forward-sexp 1) t)) - (point-marker))) - ;; sanity check - (and (not start) - (not shutup-p) - (error "Cannot find start of balanced expression to indent.")) - (and (not end) - (not shutup-p) - (error "Cannot find end of balanced expression to indent.")) - (c-progress-init start end 'c-indent-exp) - (setq progress-p t) - (goto-char start) - (beginning-of-line) - (while (< (point) end) - (if (not (looking-at "[ \t]*$")) - (c-indent-line)) - (c-progress-update) - (forward-line 1))) - ;; make sure marker is deleted - (and end - (set-marker end nil)) - (and progress-p - (c-progress-fini 'c-indent-exp)) - (goto-char here)))) - -(defun c-indent-defun () - "Re-indents the current top-level function def, struct or class declaration." - (interactive) - (let ((here (point-marker)) - (c-echo-syntactic-information-p nil) - (brace (c-least-enclosing-brace (c-parse-state)))) - (if brace - (goto-char brace) - (beginning-of-defun)) - ;; if we're sitting at b-o-b, it might be because there was no - ;; least enclosing brace and we were sitting on the defun's open - ;; brace. - (if (and (bobp) (not (eq (char-after) ?\{))) - (goto-char here)) - ;; if defun-prompt-regexp is non-nil, b-o-d might not leave us at - ;; the open brace. I consider this an Emacs bug. - (and (boundp 'defun-prompt-regexp) - defun-prompt-regexp - (looking-at defun-prompt-regexp) - (goto-char (match-end 0))) - ;; catch all errors in c-indent-exp so we can 1. give more - ;; meaningful error message, and 2. restore point - (unwind-protect - (c-indent-exp) - (goto-char here) - (set-marker here nil)))) - -(defun c-indent-region (start end) - ;; Indent every line whose first char is between START and END inclusive. - (save-excursion - (goto-char start) - ;; Advance to first nonblank line. - (skip-chars-forward " \t\n") - (beginning-of-line) - (let (endmark) - (unwind-protect - (let ((c-tab-always-indent t) - ;; shut up any echo msgs on indiv lines - (c-echo-syntactic-information-p nil) - fence) - (c-progress-init start end 'c-indent-region) - (setq endmark (copy-marker end)) - (while (and (bolp) - (not (eobp)) - (< (point) endmark)) - ;; update progress - (c-progress-update) - ;; Indent one line as with TAB. - (let (nextline sexpend sexpbeg) - ;; skip blank lines - (skip-chars-forward " \t\n") - (beginning-of-line) - ;; indent the current line - (c-indent-line) - (setq fence (point)) - (if (save-excursion - (beginning-of-line) - (looking-at "[ \t]*#")) - (forward-line 1) - (save-excursion - ;; Find beginning of following line. - (setq nextline (c-point 'bonl)) - ;; Find first beginning-of-sexp for sexp extending past - ;; this line. - (beginning-of-line) - (while (< (point) nextline) - (condition-case nil - (progn - (forward-sexp 1) - (setq sexpend (point))) - (error (setq sexpend nil) - (goto-char nextline))) - (c-forward-syntactic-ws)) - (if sexpend - (progn - ;; make sure the sexp we found really starts on the - ;; current line and extends past it - (goto-char sexpend) - (setq sexpend (point-marker)) - (c-safe (backward-sexp 1)) - (setq sexpbeg (point)))) - (if (and sexpbeg (< sexpbeg fence)) - (setq sexpbeg fence))) - ;; check to see if the next line starts a - ;; comment-only line - (save-excursion - (forward-line 1) - (skip-chars-forward " \t") - (if (looking-at c-comment-start-regexp) - (setq sexpbeg (c-point 'bol)))) - ;; If that sexp ends within the region, indent it all at - ;; once, fast. - (condition-case nil - (if (and sexpend - (> sexpend nextline) - (<= sexpend endmark)) - (progn - (goto-char sexpbeg) - (c-indent-exp 'shutup) - (c-progress-update) - (goto-char sexpend))) - (error - (goto-char sexpbeg) - (c-indent-line))) - ;; Move to following line and try again. - (and sexpend - (markerp sexpend) - (set-marker sexpend nil)) - (forward-line 1) - (setq fence (point)))))) - (set-marker endmark nil) - (c-progress-fini 'c-indent-region) - (c-echo-parsing-error) - )))) - -(defun c-mark-function () - "Put mark at end of a C, C++, or Objective-C defun, point at beginning." - (interactive) - (let ((here (point)) - ;; there should be a c-point position for 'eod - (eod (save-excursion (end-of-defun) (point))) - (state (c-parse-state)) - brace) - (while state - (setq brace (car state)) - (if (consp brace) - (goto-char (cdr brace)) - (goto-char brace)) - (setq state (cdr state))) - (if (eq (char-after) ?{) - (progn - (forward-line -1) - (while (not (or (bobp) - (looking-at "[ \t]*$"))) - (forward-line -1))) - (forward-line 1) - (skip-chars-forward " \t\n")) - (push-mark here) - (push-mark eod nil t))) - - -;; for progress reporting -(defvar c-progress-info nil) - -(defun c-progress-init (start end context) - (cond - ;; Be silent - ((not c-progress-interval)) - ;; Start the progress update messages. If this Emacs doesn't have - ;; a built-in timer, just be dumb about it. - ((not (fboundp 'current-time)) - (message "indenting region... (this may take a while)")) - ;; If progress has already been initialized, do nothing. otherwise - ;; initialize the counter with a vector of: - ;; [start end lastsec context] - (c-progress-info) - (t (setq c-progress-info (vector start - (save-excursion - (goto-char end) - (point-marker)) - (nth 1 (current-time)) - context)) - (message "indenting region...")) - )) - -(defun c-progress-update () - ;; update progress - (if (not (and c-progress-info c-progress-interval)) - nil - (let ((now (nth 1 (current-time))) - (start (aref c-progress-info 0)) - (end (aref c-progress-info 1)) - (lastsecs (aref c-progress-info 2))) - ;; should we update? currently, update happens every 2 seconds, - ;; what's the right value? - (if (< c-progress-interval (- now lastsecs)) - (progn - (message "indenting region... (%d%% complete)" - (/ (* 100 (- (point) start)) (- end start))) - (aset c-progress-info 2 now))) - ))) - -(defun c-progress-fini (context) - ;; finished - (if (not c-progress-interval) - nil - (if (or (eq context (aref c-progress-info 3)) - (eq context t)) - (progn - (set-marker (aref c-progress-info 1) nil) - (setq c-progress-info nil) - (message "indenting region...done"))))) - - - -;;; This page handles insertion and removal of backslashes for C macros. - -(defun c-backslash-region (from to delete-flag) - "Insert, align, or delete end-of-line backslashes on the lines in the region. -With no argument, inserts backslashes and aligns existing backslashes. -With an argument, deletes the backslashes. - -This function does not modify blank lines at the start of the region. -If the region ends at the start of a line, it always deletes the -backslash (if any) at the end of the previous line. - -You can put the region around an entire macro definition and use this -command to conveniently insert and align the necessary backslashes." - (interactive "r\nP") - (save-excursion - (goto-char from) - (let ((column c-backslash-column) - (endmark (make-marker))) - (move-marker endmark to) - ;; Compute the smallest column number past the ends of all the lines. - (if (not delete-flag) - (while (< (point) to) - (end-of-line) - (if (eq (char-before) ?\\) - (progn (forward-char -1) - (skip-chars-backward " \t"))) - (setq column (max column (1+ (current-column)))) - (forward-line 1))) - ;; Adjust upward to a tab column, if that doesn't push past the margin. - (if (> (% column tab-width) 0) - (let ((adjusted (* (/ (+ column tab-width -1) tab-width) tab-width))) - (if (< adjusted (window-width)) - (setq column adjusted)))) - ;; Don't modify blank lines at start of region. - (goto-char from) - (while (and (< (point) endmark) (eolp)) - (forward-line 1)) - ;; Add or remove backslashes on all the lines. - (while (< (point) endmark) - (if (and (not delete-flag) - ;; Un-backslashify the last line - ;; if the region ends right at the start of the next line. - (save-excursion - (forward-line 1) - (< (point) endmark))) - (c-append-backslash column) - (c-delete-backslash)) - (forward-line 1)) - (move-marker endmark nil))) - (c-keep-region-active)) - -(defun c-append-backslash (column) - (end-of-line) - (if (eq (char-before) ?\\) - (progn (forward-char -1) - (delete-horizontal-space) - (indent-to column)) - (indent-to column) - (insert "\\"))) - -(defun c-delete-backslash () - (end-of-line) - (or (bolp) - (progn - (forward-char -1) - (if (looking-at "\\\\") - (delete-region (1+ (point)) - (progn (skip-chars-backward " \t") (point))))))) - - -(defun c-fill-paragraph (&optional arg) - "Like \\[fill-paragraph] but handles C and C++ style comments. -If any of the current line is a comment or within a comment, -fill the comment or the paragraph of it that point is in, -preserving the comment indentation or line-starting decorations. - -Optional prefix ARG means justify paragraph as well." - (interactive "P") - (let* (comment-start-place - (first-line - ;; Check for obvious entry to comment. - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t\n") - (and (looking-at comment-start-skip) - (setq comment-start-place (point))))) - (re1 "\\|[ \t]*/\\*[ \t]*$\\|[ \t]*\\*/[ \t]*$\\|[ \t/*]*$")) - (if (save-excursion - (beginning-of-line) - (looking-at ".*//")) - (let ((fill-prefix fill-prefix) - ;; Lines containing just a comment start or just an end - ;; should not be filled into paragraphs they are next - ;; to. - (paragraph-start (concat paragraph-start re1)) - (paragraph-separate (concat paragraph-separate re1))) - (save-excursion - (beginning-of-line) - ;; Move up to first line of this comment. - (while (and (not (bobp)) - (looking-at "[ \t]*//[ \t]*[^ \t\n]")) - (forward-line -1)) - (if (not (looking-at ".*//[ \t]*[^ \t\n]")) - (forward-line 1)) - ;; Find the comment start in this line. - (re-search-forward "[ \t]*//[ \t]*") - ;; Set the fill-prefix to be what all lines except the first - ;; should start with. But do not alter a user set fill-prefix. - (if (null fill-prefix) - (setq fill-prefix (buffer-substring (match-beginning 0) - (match-end 0)))) - (save-restriction - ;; Narrow down to just the lines of this comment. - (narrow-to-region (c-point 'bol) - (save-excursion - (forward-line 1) - (while (looking-at fill-prefix) - (forward-line 1)) - (point))) - (fill-paragraph arg) - t))) - ;; else C style comments - (if (or first-line - ;; t if we enter a comment between start of function and - ;; this line. - (eq (c-in-literal) 'c) - ;; t if this line contains a comment starter. - (setq first-line - (save-excursion - (beginning-of-line) - (prog1 - (re-search-forward comment-start-skip - (save-excursion (end-of-line) - (point)) - t) - (setq comment-start-place (point)))))) - ;; Inside a comment: fill one comment paragraph. - (let ((fill-prefix - ;; The prefix for each line of this paragraph - ;; is the appropriate part of the start of this line, - ;; up to the column at which text should be indented. - (save-excursion - (beginning-of-line) - (if (looking-at "[ \t]*/\\*.*\\*/") - (progn (re-search-forward comment-start-skip) - (make-string (current-column) ?\ )) - (if first-line (forward-line 1)) - - (let ((line-width (progn (end-of-line) (current-column)))) - (beginning-of-line) - (prog1 - (buffer-substring - (point) - - ;; How shall we decide where the end of the - ;; fill-prefix is? - (progn - (beginning-of-line) - (skip-chars-forward " \t*" (c-point 'eol)) - ;; kludge alert, watch out for */, in - ;; which case fill-prefix should *not* - ;; be "*"! - (if (and (eq (char-after) ?/) - (eq (char-before) ?*)) - (forward-char -1)) - (point))) - - ;; If the comment is only one line followed - ;; by a blank line, calling move-to-column - ;; above may have added some spaces and tabs - ;; to the end of the line; the fill-paragraph - ;; function will then delete it and the - ;; newline following it, so we'll lose a - ;; blank line when we shouldn't. So delete - ;; anything move-to-column added to the end - ;; of the line. We record the line width - ;; instead of the position of the old line - ;; end because move-to-column might break a - ;; tab into spaces, and the new characters - ;; introduced there shouldn't be deleted. - - ;; If you can see a better way to do this, - ;; please make the change. This seems very - ;; messy to me. - (delete-region (progn (move-to-column line-width) - (point)) - (progn (end-of-line) (point)))))))) - - ;; Lines containing just a comment start or just an end - ;; should not be filled into paragraphs they are next - ;; to. - (paragraph-start (concat paragraph-start re1)) - (paragraph-separate (concat paragraph-separate re1)) - (chars-to-delete 0) - ) - (save-restriction - ;; Don't fill the comment together with the code - ;; following it. So temporarily exclude everything - ;; before the comment start, and everything after the - ;; line where the comment ends. If comment-start-place - ;; is non-nil, the comment starter is there. Otherwise, - ;; point is inside the comment. - (narrow-to-region (save-excursion - (if comment-start-place - (goto-char comment-start-place) - (search-backward "/*")) - (if (and (not c-hanging-comment-starter-p) - (looking-at - (concat c-comment-start-regexp - "[ \t]*$"))) - (forward-line 1)) - ;; Protect text before the comment - ;; start by excluding it. Add - ;; spaces to bring back proper - ;; indentation of that point. - (let ((column (current-column))) - (prog1 (point) - (setq chars-to-delete column) - (insert-char ?\ column)))) - (save-excursion - (if comment-start-place - (goto-char (+ comment-start-place 2))) - (search-forward "*/" nil 'move) - (forward-line 1) - (point))) - (fill-paragraph arg) - (save-excursion - ;; Delete the chars we inserted to avoid clobbering - ;; the stuff before the comment start. - (goto-char (point-min)) - (if (> chars-to-delete 0) - (delete-region (point) (+ (point) chars-to-delete))) - ;; Find the comment ender (should be on last line of - ;; buffer, given the narrowing) and don't leave it on - ;; its own line, unless that's the style that's desired. - (goto-char (point-max)) - (forward-line -1) - (search-forward "*/" nil 'move) - (beginning-of-line) - (if (and c-hanging-comment-ender-p - (looking-at "[ \t]*\\*/")) - ;(delete-indentation))))) - (let ((fill-column (+ fill-column 9999))) - (forward-line -1) - (fill-region-as-paragraph (point) (point-max)))))) - t))))) - - -(provide 'cc-cmds) -;;; cc-cmds.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-compat.el --- a/lisp/cc-mode/cc-compat.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Author: 1994-1997 Barry A. Warsaw -;; Maintainer: cc-mode-help@python.org -;; Created: August 1994, split from cc-mode.el -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; Boring old c-mode.el (BOCM) is confusion and brain melt. cc-mode.el -;; is clarity of thought and purity of chi. If you are still unwilling -;; to accept enlightenment, this might help, or it may prolong your -;; agony. -;; -;; To use, add the following to your c-mode-hook: -;; -;; (require 'cc-compat) -;; (c-set-style "BOCM") - -;;; Code: - -(eval-when-compile - (require 'cc-styles) - (require 'cc-engine)) - - -;; In case c-mode.el isn't loaded -(defvar c-indent-level 2 - "*Indentation of C statements with respect to containing block.") -(defvar c-brace-imaginary-offset 0 - "*Imagined indentation of a C open brace that actually follows a statement.") -(defvar c-brace-offset 0 - "*Extra indentation for braces, compared with other text in same context.") -(defvar c-argdecl-indent 5 - "*Indentation level of declarations of C function arguments.") -(defvar c-label-offset -2 - "*Offset of C label lines and case statements relative to usual indentation.") -(defvar c-continued-statement-offset 2 - "*Extra indent for lines not starting new statements.") -(defvar c-continued-brace-offset 0 - "*Extra indent for substatements that start with open-braces. -This is in addition to c-continued-statement-offset.") - - - -;; these offsets are taken by brute force testing c-mode.el, since -;; there's no logic to what it does. -(let* ((offsets '(c-offsets-alist . - ((defun-block-intro . cc-block-intro-offset) - (statement-block-intro . cc-block-intro-offset) - (defun-open . 0) - (class-open . 0) - (inline-open . c-brace-offset) - (block-open . c-brace-offset) - (block-close . cc-block-close-offset) - (brace-list-open . c-brace-offset) - (substatement-open . cc-substatement-open-offset) - (substatement . c-continued-statement-offset) - (knr-argdecl-intro . c-argdecl-indent) - (case-label . c-label-offset) - (access-label . c-label-offset) - (label . c-label-offset) - )))) - (c-add-style "BOCM" offsets)) - - -(defun cc-block-intro-offset (langelem) - ;; taken directly from calculate-c-indent confusion - (save-excursion - (c-backward-syntactic-ws) - (if (eq (char-before) ?{) - (forward-char -1) - (goto-char (cdr langelem))) - (let* ((curcol (save-excursion - (goto-char (cdr langelem)) - (current-column))) - (bocm-lossage - ;; If no previous statement, indent it relative to line - ;; brace is on. For open brace in column zero, don't let - ;; statement start there too. If c-indent-level is zero, - ;; use c-brace-offset + c-continued-statement-offset - ;; instead. For open-braces not the first thing in a line, - ;; add in c-brace-imaginary-offset. - (+ (if (and (bolp) (zerop c-indent-level)) - (+ c-brace-offset c-continued-statement-offset) - c-indent-level) - ;; Move back over whitespace before the openbrace. If - ;; openbrace is not first nonwhite thing on the line, - ;; add the c-brace-imaginary-offset. - (progn (skip-chars-backward " \t") - (if (bolp) 0 c-brace-imaginary-offset)) - ;; If the openbrace is preceded by a parenthesized exp, - ;; move to the beginning of that; possibly a different - ;; line - (progn - (if (eq (char-before) ?\)) - (forward-sexp -1)) - ;; Get initial indentation of the line we are on. - (current-indentation))))) - (- bocm-lossage curcol)))) - - -(defun cc-block-close-offset (langelem) - (save-excursion - (let* ((here (point)) - bracep - (curcol (progn - (goto-char (cdr langelem)) - (current-column))) - (bocm-lossage (progn - (goto-char (cdr langelem)) - (if (eq (char-after) ?{) - (setq bracep t) - (goto-char here) - (beginning-of-line) - (backward-up-list 1) - (forward-char 1) - (c-forward-syntactic-ws)) - (current-column)))) - (- bocm-lossage curcol - (if bracep 0 c-indent-level))))) - - -(defun cc-substatement-open-offset (langelem) - (+ c-continued-statement-offset c-continued-brace-offset)) - - -(provide 'cc-compat) -;;; cc-compat.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-defs.el --- a/lisp/cc-mode/cc-defs.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -;;; cc-defs.el --- definitions for CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;; Figure out what features this Emacs has -(defconst c-emacs-features - (let ((infodock-p (boundp 'infodock-version)) - (comments - ;; XEmacs 19 and beyond use 8-bit modify-syntax-entry flags. - ;; Emacs 19 uses a 1-bit flag. We will have to set up our - ;; syntax tables differently to handle this. - (let ((table (copy-syntax-table)) - entry) - (modify-syntax-entry ?a ". 12345678" table) - (cond - ;; XEmacs 19, and beyond Emacs 19.34 - ((arrayp table) - (setq entry (aref table ?a)) - ;; In Emacs, table entries are cons cells - (if (consp entry) (setq entry (car entry)))) - ;; XEmacs 20 - ((fboundp 'get-char-table) (setq entry (get-char-table ?a table))) - ;; before and including Emacs 19.34 - ((and (fboundp 'char-table-p) - (char-table-p table)) - (setq entry (car (char-table-range table [?a])))) - ;; incompatible - (t (error "CC Mode is incompatible with this version of Emacs"))) - (if (= (logand (lsh entry -16) 255) 255) - '8-bit - '1-bit)))) - (if infodock-p - (list comments 'infodock) - (list comments))) - "A list of features extant in the Emacs you are using. -There are many flavors of Emacs out there, each with different -features supporting those needed by CC Mode. Here's the current -supported list, along with the values for this variable: - - XEmacs 19: (8-bit) - XEmacs 20: (8-bit) - Emacs 19: (1-bit) - -Infodock (based on XEmacs) has an additional symbol on this list: -'infodock.") - - - -(defsubst c-point (position) - ;; Returns the value of point at certain commonly referenced POSITIONs. - ;; POSITION can be one of the following symbols: - ;; - ;; bol -- beginning of line - ;; eol -- end of line - ;; bod -- beginning of defun - ;; boi -- back to indentation - ;; ionl -- indentation of next line - ;; iopl -- indentation of previous line - ;; bonl -- beginning of next line - ;; bopl -- beginning of previous line - ;; - ;; This function does not modify point or mark. - (let ((here (point))) - (cond - ((eq position 'bol) (beginning-of-line)) - ((eq position 'eol) (end-of-line)) - ((eq position 'bod) - (beginning-of-defun) - ;; if defun-prompt-regexp is non-nil, b-o-d won't leave us at - ;; the open brace. - (and defun-prompt-regexp - (looking-at defun-prompt-regexp) - (goto-char (match-end 0))) - ) - ((eq position 'boi) (back-to-indentation)) - ((eq position 'bonl) (forward-line 1)) - ((eq position 'bopl) (forward-line -1)) - ((eq position 'iopl) - (forward-line -1) - (back-to-indentation)) - ((eq position 'ionl) - (forward-line 1) - (back-to-indentation)) - (t (error "unknown buffer position requested: %s" position)) - ) - (prog1 - (point) - (goto-char here)))) - -(defmacro c-safe (&rest body) - ;; safely execute BODY, return nil if an error occurred - (` (condition-case nil - (progn (,@ body)) - (error nil)))) - -(defmacro c-add-syntax (symbol &optional relpos) - ;; a simple macro to append the syntax in symbol to the syntax list. - ;; try to increase performance by using this macro - (` (setq syntax (cons (cons (, symbol) (, relpos)) syntax)))) - -(defsubst c-auto-newline () - ;; if auto-newline feature is turned on, insert a newline character - ;; and return t, otherwise return nil. - (and c-auto-newline - (not (c-in-literal)) - (not (newline)))) - -(defsubst c-intersect-lists (list alist) - ;; return the element of ALIST that matches the first element found - ;; in LIST. Uses assq. - (let (match) - (while (and list - (not (setq match (assq (car list) alist)))) - (setq list (cdr list))) - match)) - -(defsubst c-lookup-lists (list alist1 alist2) - ;; first, find the first entry from LIST that is present in ALIST1, - ;; then find the entry in ALIST2 for that entry. - (assq (car (c-intersect-lists list alist1)) alist2)) - -(defsubst c-langelem-col (langelem &optional preserve-point) - ;; convenience routine to return the column of langelem's relpos. - ;; Leaves point at the relpos unless preserve-point is non-nil. - (let ((here (point))) - (goto-char (cdr langelem)) - (prog1 (current-column) - (if preserve-point - (goto-char here)) - ))) - -(defsubst c-update-modeline () - ;; set the c-auto-hungry-string for the correct designation on the modeline - (setq c-auto-hungry-string - (if c-auto-newline - (if c-hungry-delete-key "/ah" "/a") - (if c-hungry-delete-key "/h" nil))) - (force-mode-line-update)) - -(defsubst c-keep-region-active () - ;; Do whatever is necessary to keep the region active in XEmacs. - ;; Ignore byte-compiler warnings you might see. This is not needed - ;; for Emacs. - (and (boundp 'zmacs-region-stays) - (setq zmacs-region-stays t))) - - -(provide 'cc-defs) -;;; cc-defs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-engine.el --- a/lisp/cc-mode/cc-engine.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1722 +0,0 @@ -;;; cc-engine.el --- core syntax guessing engine for CC mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;; KLUDGE ALERT: c-maybe-labelp is used to pass information between -;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A -;; better way should be implemented, but this will at least shut up -;; the byte compiler. -(defvar c-maybe-labelp nil) - -;; WARNING WARNING WARNING -;; -;; Be *exceptionally* careful about modifications to this function! -;; Much of CC Mode depends on this Doing The Right Thing. If you -;; break it you will be sorry. If you think you know how this works, -;; you probably don't. No human on Earth does! :-) -;; -;; WARNING WARNING WARNING - -(defun c-beginning-of-statement-1 (&optional lim) - ;; move to the start of the current statement, or the previous - ;; statement if already at the beginning of one. - (let ((firstp t) - (substmt-p t) - donep c-in-literal-cache saved - (last-begin (point))) - ;; first check for bare semicolon - (if (and (progn (c-backward-syntactic-ws lim) - (eq (char-before) ?\;)) - (c-safe (progn (forward-char -1) - (setq saved (point)) - t)) - (progn (c-backward-syntactic-ws lim) - (memq (char-before) '(?\; ?{ ?:))) - ) - (setq last-begin saved) - (goto-char last-begin) - (while (not donep) - ;; stop at beginning of buffer - (if (bobp) (setq donep t) - ;; go backwards one balanced expression, but be careful of - ;; unbalanced paren being reached - (if (not (c-safe (progn (backward-sexp 1) t))) - (progn - (if firstp - (backward-up-list 1) - (goto-char last-begin)) - ;; skip over any unary operators, or other special - ;; characters appearing at front of identifier - (save-excursion - (c-backward-syntactic-ws lim) - (skip-chars-backward "-+!*&:.~ \t\n") - (if (eq (char-before) ?\() - (setq last-begin (point)))) - (goto-char last-begin) - (setq last-begin (point) - donep t))) - - (setq c-maybe-labelp nil) - ;; see if we're in a literal. if not, then this bufpos may be - ;; a candidate for stopping - (cond - ;; CASE 0: did we hit the error condition above? - (donep) - ;; CASE 1: are we in a literal? - ((eq (c-in-literal lim) 'pound) - (beginning-of-line)) - ;; CASE 2: some other kind of literal? - ((c-in-literal lim)) - ;; CASE 3: are we looking at a conditional keyword? - ((or (looking-at c-conditional-key) - (and (eq (char-after) ?\() - (save-excursion - (forward-sexp 1) - (c-forward-syntactic-ws) - (not (eq (char-after) ?\;))) - (let ((here (point)) - (foundp (progn - (c-backward-syntactic-ws lim) - (forward-word -1) - (and lim - (<= lim (point)) - (not (c-in-literal lim)) - (not (eq (char-before) ?_)) - (looking-at c-conditional-key) - )))) - ;; did we find a conditional? - (if (not foundp) - (goto-char here)) - foundp))) - ;; are we in the middle of an else-if clause? - (if (save-excursion - (and (not substmt-p) - (c-safe (progn (forward-sexp -1) t)) - (looking-at "\\[ \t\n]+\\") - (not (c-in-literal lim)))) - (progn - (forward-sexp -1) - (c-backward-to-start-of-if lim))) - ;; are we sitting at an else clause, that we are not a - ;; substatement of? - (if (and (not substmt-p) - (looking-at "\\[^_]")) - (c-backward-to-start-of-if lim)) - ;; are we sitting at the while of a do-while? - (if (and (looking-at "\\[^_]") - (c-backward-to-start-of-do lim)) - (setq substmt-p nil)) - (setq last-begin (point) - donep substmt-p)) - ;; CASE 4: are we looking at a label? - ((looking-at c-label-key)) - ;; CASE 5: is this the first time we're checking? - (firstp (setq firstp nil - substmt-p (not (c-crosses-statement-barrier-p - (point) last-begin)) - last-begin (point))) - ;; CASE 6: have we crossed a statement barrier? - ((c-crosses-statement-barrier-p (point) last-begin) - (setq donep t)) - ;; CASE 7: ignore labels - ((and c-maybe-labelp - (or (and c-access-key (looking-at c-access-key)) - ;; with switch labels, we have to go back further - ;; to try to pick up the case or default - ;; keyword. Potential bogosity alert: we assume - ;; `case' or `default' is first thing on line - (let ((here (point))) - (beginning-of-line) - (c-forward-syntactic-ws) - (if (looking-at c-switch-label-key) - t - (goto-char here) - nil)) - (looking-at c-label-key)))) - ;; CASE 8: ObjC or Java method def - ((and c-method-key - (setq last-begin (c-in-method-def-p))) - (setq donep t)) - ;; CASE 9: nothing special - (t (setq last-begin (point))) - )))) - (goto-char last-begin) - ;; we always do want to skip over non-whitespace modifier - ;; characters that didn't get skipped above - (skip-chars-backward "-+!*&:.~" (c-point 'boi)))) - -(defun c-end-of-statement-1 () - (condition-case nil - (let (beg end found) - (while (and (not (eobp)) - (progn - (setq beg (point)) - (forward-sexp 1) - (setq end (point)) - (goto-char beg) - (setq found nil) - (while (and (not found) - (re-search-forward "[;{}]" end t)) - (if (not (c-in-literal beg)) - (setq found t))) - (not found))) - (goto-char end)) - (re-search-backward "[;{}]") - (forward-char 1)) - (error - (let ((beg (point))) - (c-safe (backward-up-list -1)) - (let ((end (point))) - (goto-char beg) - (search-forward ";" end 'move))) - ))) - - -(defun c-crosses-statement-barrier-p (from to) - ;; Does buffer positions FROM to TO cross a C statement boundary? - (let ((here (point)) - (lim from) - crossedp) - (condition-case () - (progn - (goto-char from) - (while (and (not crossedp) - (< (point) to)) - (skip-chars-forward "^;{}:" to) - (if (not (c-in-literal lim)) - (progn - (if (memq (char-after) '(?\; ?{ ?})) - (setq crossedp t) - (if (eq (char-after) ?:) - (setq c-maybe-labelp t)) - (forward-char 1)) - (setq lim (point))) - (forward-char 1)))) - (error (setq crossedp nil))) - (goto-char here) - crossedp)) - - -;; Skipping of "syntactic whitespace", defined as lexical whitespace, -;; C and C++ style comments, and preprocessor directives. Search no -;; farther back or forward than optional LIM. If LIM is omitted, -;; `beginning-of-defun' is used for backward skipping, point-max is -;; used for forward skipping. - -(defun c-forward-syntactic-ws (&optional lim) - ;; Forward skip of syntactic whitespace for Emacs 19. - (save-restriction - (let* ((lim (or lim (point-max))) - (here lim) - (hugenum (point-max))) - (narrow-to-region lim (point)) - (while (/= here (point)) - (setq here (point)) - (forward-comment hugenum) - ;; skip preprocessor directives - (if (and (eq (char-after) ?#) - (= (c-point 'boi) (point))) - (end-of-line) - ))))) - -(defun c-backward-syntactic-ws (&optional lim) - ;; Backward skip over syntactic whitespace for Emacs 19. - (save-restriction - (let* ((lim (or lim (c-point 'bod))) - (here lim) - (hugenum (- (point-max)))) - (if (< lim (point)) - (progn - (narrow-to-region lim (point)) - (while (/= here (point)) - (setq here (point)) - (forward-comment hugenum) - (if (eq (c-in-literal lim) 'pound) - (beginning-of-line)) - ))) - ))) - - -;; Return `c' if in a C-style comment, `c++' if in a C++ style -;; comment, `string' if in a string literal, `pound' if on a -;; preprocessor line, or nil if not in a comment at all. Optional LIM -;; is used as the backward limit of the search. If omitted, or nil, -;; `beginning-of-defun' is used." - -(defun c-in-literal (&optional lim) - ;; Determine if point is in a C++ literal. we cache the last point - ;; calculated if the cache is enabled - (if (and (boundp 'c-in-literal-cache) - c-in-literal-cache - (= (point) (aref c-in-literal-cache 0))) - (aref c-in-literal-cache 1) - (let ((rtn (save-excursion - (let* ((lim (or lim (c-point 'bod))) - (here (point)) - (state (parse-partial-sexp lim (point)))) - (cond - ((nth 3 state) 'string) - ((nth 4 state) (if (nth 7 state) 'c++ 'c)) - ((progn - (goto-char here) - (beginning-of-line) - (looking-at "[ \t]*#")) - 'pound) - (t nil)))))) - ;; cache this result if the cache is enabled - (and (boundp 'c-in-literal-cache) - (setq c-in-literal-cache (vector (point) rtn))) - rtn))) - - -;; utilities for moving and querying around syntactic elements -(defvar c-parsing-error nil) - -(defun c-parse-state () - ;; Finds and records all open parens between some important point - ;; earlier in the file and point. - ;; - ;; if there's a state cache, return it - (setq c-parsing-error nil) - (if (boundp 'c-state-cache) c-state-cache - (let* (at-bob - (pos (save-excursion - ;; go back 2 bods, but ignore any bogus positions - ;; returned by beginning-of-defun (i.e. open paren - ;; in column zero) - (let ((cnt 2)) - (while (not (or at-bob (zerop cnt))) - (beginning-of-defun) - (if (eq (char-after) ?\{) - (setq cnt (1- cnt))) - (if (bobp) - (setq at-bob t)))) - (point))) - (here (save-excursion - ;;(skip-chars-forward " \t}") - (point))) - (last-bod pos) (last-pos pos) - placeholder state sexp-end) - ;; cache last bod position - (while (catch 'backup-bod - (setq state nil) - (while (and pos (< pos here)) - (setq last-pos pos) - (if (and (setq pos (c-safe (scan-lists pos 1 -1))) - (<= pos here)) - (progn - (setq sexp-end (c-safe (scan-sexps (1- pos) 1))) - (if (and sexp-end - (<= sexp-end here)) - ;; we want to record both the start and end - ;; of this sexp, but we only want to record - ;; the last-most of any of them before here - (progn - (if (eq (char-after (1- pos)) ?\{) - (setq state (cons (cons (1- pos) sexp-end) - (if (consp (car state)) - (cdr state) - state)))) - (setq pos sexp-end)) - ;; we're contained in this sexp so put pos on - ;; front of list - (setq state (cons (1- pos) state)))) - ;; something bad happened. check to see if we - ;; crossed an unbalanced close brace. if so, we - ;; didn't really find the right `important bufpos' - ;; so lets back up and try again - (if (and (not pos) (not at-bob) - (setq placeholder - (c-safe (scan-lists last-pos 1 1))) - ;;(char-after (1- placeholder)) - (<= placeholder here) - (eq (char-after (1- placeholder)) ?\})) - (while t - (setq last-bod (c-safe (scan-lists last-bod -1 1))) - (if (not last-bod) - (progn - ;; bogus, but what can we do here? - (setq c-parsing-error (1- placeholder)) - (throw 'backup-bod nil)) - (setq at-bob (= last-bod (point-min)) - pos last-bod) - (if (= (char-after last-bod) ?\{) - (throw 'backup-bod t))) - )) ;end-if - )) ;end-while - nil)) - state))) - -(defun c-whack-state (bufpos state) - ;; whack off any state information that appears on STATE which lies - ;; after the bounds of BUFPOS. - (let (newstate car) - (while state - (setq car (car state) - state (cdr state)) - (if (consp car) - ;; just check the car, because in a balanced brace - ;; expression, it must be impossible for the corresponding - ;; close brace to be before point, but the open brace to be - ;; after. - (if (<= bufpos (car car)) - nil ; whack it off - ;; its possible that the open brace is before bufpos, but - ;; the close brace is after. In that case, convert this - ;; to a non-cons element. - (if (<= bufpos (cdr car)) - (setq newstate (append newstate (list (car car)))) - ;; we know that both the open and close braces are - ;; before bufpos, so we also know that everything else - ;; on state is before bufpos, so we can glom up the - ;; whole thing and exit. - (setq newstate (append newstate (list car) state) - state nil))) - (if (<= bufpos car) - nil ; whack it off - ;; it's before bufpos, so everything else should too - (setq newstate (append newstate (list car) state) - state nil)))) - newstate)) - -(defun c-hack-state (bufpos which state) - ;; Using BUFPOS buffer position, and WHICH (must be 'open or - ;; 'close), hack the c-parse-state STATE and return the results. - (if (eq which 'open) - (let ((car (car state))) - (if (or (null car) - (consp car) - (/= bufpos car)) - (cons bufpos state) - state)) - (if (not (eq which 'close)) - (error "c-hack-state, bad argument: %s" which)) - ;; 'close brace - (let ((car (car state)) - (cdr (cdr state))) - (if (consp car) - (setq car (car cdr) - cdr (cdr cdr))) - ;; TBD: is this test relevant??? - (if (consp car) - state ;on error, don't change - ;; watch out for balanced expr already on cdr of list - (cons (cons car bufpos) - (if (consp (car cdr)) - (cdr cdr) cdr)) - )))) - -(defun c-adjust-state (from to shift state) - ;; Adjust all points in state that lie in the region FROM..TO by - ;; SHIFT amount (as would be returned by c-indent-line). - (mapcar - (function - (lambda (e) - (if (consp e) - (let ((car (car e)) - (cdr (cdr e))) - (if (and (<= from car) (< car to)) - (setcar e (+ shift car))) - (if (and (<= from cdr) (< cdr to)) - (setcdr e (+ shift cdr)))) - (if (and (<= from e) (< e to)) - (setq e (+ shift e)))) - e)) - state)) - - -(defun c-beginning-of-inheritance-list (&optional lim) - ;; Go to the first non-whitespace after the colon that starts a - ;; multiple inheritance introduction. Optional LIM is the farthest - ;; back we should search. - (let ((lim (or lim (c-point 'bod))) - (placeholder (progn - (back-to-indentation) - (point)))) - (c-backward-syntactic-ws lim) - (while (and (> (point) lim) - (memq (char-before) '(?, ?:)) - (progn - (beginning-of-line) - (setq placeholder (point)) - (skip-chars-forward " \t") - (not (looking-at c-class-key)) - )) - (c-backward-syntactic-ws lim)) - (goto-char placeholder) - (skip-chars-forward "^:" (c-point 'eol)))) - -(defun c-beginning-of-macro (&optional lim) - ;; Go to the beginning of the macro. Right now we don't support - ;; multi-line macros too well - (back-to-indentation)) - -(defun c-in-method-def-p () - ;; Return nil if we aren't in a method definition, otherwise the - ;; position of the initial [+-]. - (save-excursion - (beginning-of-line) - (and c-method-key - (looking-at c-method-key) - (point)) - )) - -(defun c-just-after-func-arglist-p (&optional containing) - ;; Return t if we are between a function's argument list closing - ;; paren and its opening brace. Note that the list close brace - ;; could be followed by a "const" specifier or a member init hanging - ;; colon. Optional CONTAINING is position of containing s-exp open - ;; brace. If not supplied, point is used as search start. - (save-excursion - (c-backward-syntactic-ws) - (let ((checkpoint (or containing (point)))) - (goto-char checkpoint) - ;; could be looking at const specifier - (if (and (eq (char-before) ?t) - (forward-word -1) - (looking-at "\\")) - (c-backward-syntactic-ws) - ;; otherwise, we could be looking at a hanging member init - ;; colon - (goto-char checkpoint) - (if (and (eq (char-before) ?:) - (progn - (forward-char -1) - (c-backward-syntactic-ws) - (looking-at "[ \t\n]*:\\([^:]+\\|$\\)"))) - nil - (goto-char checkpoint)) - ) - (and (eq (char-before) ?\)) - ;; check if we are looking at a method def - (or (not c-method-key) - (progn - (forward-sexp -1) - (forward-char -1) - (c-backward-syntactic-ws) - (not (or (memq (char-before) '(?- ?+)) - ;; or a class category - (progn - (forward-sexp -2) - (looking-at c-class-key)) - ))))) - ))) - -;; defuns to look backwards for things -(defun c-backward-to-start-of-do (&optional lim) - ;; Move to the start of the last "unbalanced" do expression. - ;; Optional LIM is the farthest back to search. If none is found, - ;; nil is returned and point is left unchanged, otherwise t is returned. - (let ((do-level 1) - (case-fold-search nil) - (lim (or lim (c-point 'bod))) - (here (point)) - foundp) - (while (not (zerop do-level)) - ;; we protect this call because trying to execute this when the - ;; while is not associated with a do will throw an error - (condition-case nil - (progn - (backward-sexp 1) - (cond - ((memq (c-in-literal lim) '(c c++))) - ((looking-at "while\\b[^_]") - (setq do-level (1+ do-level))) - ((looking-at "do\\b[^_]") - (if (zerop (setq do-level (1- do-level))) - (setq foundp t))) - ((<= (point) lim) - (setq do-level 0) - (goto-char lim)))) - (error - (goto-char lim) - (setq do-level 0)))) - (if (not foundp) - (goto-char here)) - foundp)) - -(defun c-backward-to-start-of-if (&optional lim) - ;; Move to the start of the last "unbalanced" if and return t. If - ;; none is found, and we are looking at an if clause, nil is - ;; returned. If none is found and we are looking at an else clause, - ;; an error is thrown. - (let ((if-level 1) - (here (c-point 'bol)) - (case-fold-search nil) - (lim (or lim (c-point 'bod))) - (at-if (looking-at "if\\b[^_]"))) - (catch 'orphan-if - (while (and (not (bobp)) - (not (zerop if-level))) - (c-backward-syntactic-ws) - (condition-case nil - (backward-sexp 1) - (error - (if at-if - (throw 'orphan-if nil) - (error "No matching `if' found for `else' on line %d." - (1+ (count-lines 1 here)))))) - (cond - ((looking-at "else\\b[^_]") - (setq if-level (1+ if-level))) - ((looking-at "if\\b[^_]") - ;; check for else if... skip over - (let ((here (point))) - (c-safe (forward-sexp -1)) - (if (looking-at "\\[ \t]+\\") - nil - (setq if-level (1- if-level)) - (goto-char here)))) - ((< (point) lim) - (setq if-level 0) - (goto-char lim)) - )) - t))) - -(defun c-skip-conditional () - ;; skip forward over conditional at point, including any predicate - ;; statements in parentheses. No error checking is performed. - (forward-sexp (cond - ;; else if() - ((looking-at "\\[ \t]+\\") 3) - ;; do, else, try, finally - ((looking-at "\\<\\(do\\|else\\|try\\|finally\\)\\>") 1) - ;; for, if, while, switch, catch, synchronized - (t 2)))) - -(defun c-skip-case-statement-forward (state &optional lim) - ;; skip forward over case/default bodies, with optional maximal - ;; limit. if no next case body is found, nil is returned and point - ;; is not moved - (let ((lim (or lim (point-max))) - (here (point)) - donep foundp bufpos - (safepos (point)) - (balanced (car state))) - ;; search until we've passed the limit, or we've found our match - (while (and (< (point) lim) - (not donep)) - (setq safepos (point)) - ;; see if we can find a case statement, not in a literal - (if (and (re-search-forward c-switch-label-key lim 'move) - (setq bufpos (match-beginning 0)) - (not (c-in-literal safepos)) - (/= bufpos here)) - ;; if we crossed into a balanced sexp, we know the case is - ;; not part of our switch statement, so just bound over the - ;; sexp and keep looking. - (if (and (consp balanced) - (> bufpos (car balanced)) - (< bufpos (cdr balanced))) - (goto-char (cdr balanced)) - (goto-char bufpos) - (setq donep t - foundp t)))) - (if (not foundp) - (goto-char here)) - foundp)) - -(defun c-search-uplist-for-classkey (brace-state) - ;; search for the containing class, returning a 2 element vector if - ;; found. aref 0 contains the bufpos of the class key, and aref 1 - ;; contains the bufpos of the open brace. - (if (null brace-state) - ;; no brace-state means we cannot be inside a class - nil - (let ((carcache (car brace-state)) - search-start search-end) - (if (consp carcache) - ;; a cons cell in the first element means that there is some - ;; balanced sexp before the current bufpos. this we can - ;; ignore. the nth 1 and nth 2 elements define for us the - ;; search boundaries - (setq search-start (nth 2 brace-state) - search-end (nth 1 brace-state)) - ;; if the car was not a cons cell then nth 0 and nth 1 define - ;; for us the search boundaries - (setq search-start (nth 1 brace-state) - search-end (nth 0 brace-state))) - ;; search-end cannot be a cons cell - (and (consp search-end) - (error "consp search-end: %s" search-end)) - ;; if search-end is nil, or if the search-end character isn't an - ;; open brace, we are definitely not in a class - (if (or (not search-end) - (< search-end (point-min)) - (not (eq (char-after search-end) ?{))) - nil - ;; now, we need to look more closely at search-start. if - ;; search-start is nil, then our start boundary is really - ;; point-min. - (if (not search-start) - (setq search-start (point-min)) - ;; if search-start is a cons cell, then we can start - ;; searching from the end of the balanced sexp just ahead of - ;; us - (if (consp search-start) - (setq search-start (cdr search-start)))) - ;; now we can do a quick regexp search from search-start to - ;; search-end and see if we can find a class key. watch for - ;; class like strings in literals - (save-excursion - (save-restriction - (goto-char search-start) - (let ((search-key (concat c-class-key "\\|extern[^_]")) - foundp class match-end) - (while (and (not foundp) - (progn - (c-forward-syntactic-ws) - (> search-end (point))) - (re-search-forward search-key search-end t)) - (setq class (match-beginning 0) - match-end (match-end 0)) - (if (c-in-literal search-start) - nil ; its in a comment or string, ignore - (goto-char class) - (skip-chars-forward " \t\n") - (setq foundp (vector (c-point 'boi) search-end)) - (cond - ;; check for embedded keywords - ((let ((char (char-after (1- class)))) - (and char - (memq (char-syntax char) '(?w ?_)))) - (goto-char match-end) - (setq foundp nil)) - ;; make sure we're really looking at the start of a - ;; class definition, and not a forward decl, return - ;; arg, template arg list, or an ObjC or Java method. - ((and c-method-key - (re-search-forward c-method-key search-end t)) - (setq foundp nil)) - ;; Its impossible to define a regexp for this, and - ;; nearly so to do it programmatically. - ;; - ;; ; picks up forward decls - ;; = picks up init lists - ;; ) picks up return types - ;; > picks up templates, but remember that we can - ;; inherit from templates! - ((let ((skipchars "^;=)")) - ;; try to see if we found the `class' keyword - ;; inside a template arg list - (save-excursion - (skip-chars-backward "^<>" search-start) - (if (eq (char-before) ?<) - (setq skipchars (concat skipchars ">")))) - (skip-chars-forward skipchars search-end) - (/= (point) search-end)) - (setq foundp nil)) - ))) - foundp)) - ))))) - -(defun c-inside-bracelist-p (containing-sexp brace-state) - ;; return the buffer position of the beginning of the brace list - ;; statement if we're inside a brace list, otherwise return nil. - ;; CONTAINING-SEXP is the buffer pos of the innermost containing - ;; paren. BRACE-STATE is the remainder of the state of enclosing braces - ;; - ;; N.B.: This algorithm can potentially get confused by cpp macros - ;; places in inconvenient locations. Its a trade-off we make for - ;; speed. - (or - ;; this will pick up enum lists - (condition-case () - (save-excursion - (goto-char containing-sexp) - (forward-sexp -1) - (if (and (or (looking-at "enum[\t\n ]+") - (progn (forward-sexp -1) - (looking-at "enum[\t\n ]+"))) - (progn (c-end-of-statement-1) - (> (point) containing-sexp))) - (point))) - (error nil)) - ;; this will pick up array/aggregate init lists, even if they are nested. - (save-excursion - (let (bufpos failedp) - (while (and (not bufpos) - containing-sexp) - (if (consp containing-sexp) - (setq containing-sexp (car brace-state) - brace-state (cdr brace-state)) - ;; see if significant character just before brace is an equal - (goto-char containing-sexp) - (setq failedp nil) - (condition-case () - (progn - (forward-sexp -1) - (forward-sexp 1) - (c-forward-syntactic-ws containing-sexp)) - (error (setq failedp t))) - (if (or failedp (not (eq (char-after) ?=))) - ;; lets see if we're nested. find the most nested - ;; containing brace - (setq containing-sexp (car brace-state) - brace-state (cdr brace-state)) - ;; we've hit the beginning of the aggregate list - (c-beginning-of-statement-1 (c-most-enclosing-brace brace-state)) - (setq bufpos (point))) - )) - bufpos)) - )) - - -(defun c-most-enclosing-brace (state) - ;; return the bufpos of the most enclosing brace that hasn't been - ;; narrowed out by any enclosing class, or nil if none was found - (let (enclosingp) - (while (and state (not enclosingp)) - (setq enclosingp (car state) - state (cdr state)) - (if (consp enclosingp) - (setq enclosingp nil) - (if (> (point-min) enclosingp) - (setq enclosingp nil)) - (setq state nil))) - enclosingp)) - -(defun c-least-enclosing-brace (state) - ;; return the bufpos of the least (highest) enclosing brace that - ;; hasn't been narrowed out by any enclosing class, or nil if none - ;; was found. - (c-most-enclosing-brace (nreverse state))) - -(defun c-safe-position (bufpos state) - ;; return the closest known safe position higher up than point - (let ((safepos nil)) - (while state - (setq safepos - (if (consp (car state)) - (cdr (car state)) - (car state))) - (if (< safepos bufpos) - (setq state nil) - (setq state (cdr state)))) - safepos)) - -(defun c-narrow-out-enclosing-class (state lim) - ;; narrow the buffer so that the enclosing class is hidden - (let (inclass-p) - (and state - (setq inclass-p (c-search-uplist-for-classkey state)) - (narrow-to-region - (progn - (goto-char (1+ (aref inclass-p 1))) - (skip-chars-forward " \t\n" lim) - ;; if point is now left of the class opening brace, we're - ;; hosed, so try a different tact - (if (<= (point) (aref inclass-p 1)) - (progn - (goto-char (1+ (aref inclass-p 1))) - (c-forward-syntactic-ws lim))) - (point)) - ;; end point is the end of the current line - (progn - (goto-char lim) - (c-point 'eol)))) - ;; return the class vector - inclass-p)) - - -;; This function implements the main decision tree for determining the -;; syntactic analysis of the current line of code. Yes, it's huge and -;; bloated! - -(defun c-guess-basic-syntax () - (save-excursion - (save-restriction - (beginning-of-line) - (let* ((indent-point (point)) - (case-fold-search nil) - (fullstate (c-parse-state)) - (state fullstate) - (in-method-intro-p (and (eq major-mode 'objc-mode) - c-method-key - (looking-at c-method-key))) - literal containing-sexp char-before-ip char-after-ip lim - syntax placeholder c-in-literal-cache inswitch-p - injava-inher - ;; narrow out any enclosing class or extern "C" block - (inclass-p (c-narrow-out-enclosing-class state indent-point)) - (inextern-p (and inclass-p - (save-excursion - (save-restriction - (widen) - (goto-char (aref inclass-p 0)) - (looking-at "extern[^_]"))))) - ) - - ;; get the buffer position of the most nested opening brace, - ;; if there is one, and it hasn't been narrowed out - (save-excursion - (goto-char indent-point) - (skip-chars-forward " \t}") - (skip-chars-backward " \t") - (while (and state - (not in-method-intro-p) - (not containing-sexp)) - (setq containing-sexp (car state) - state (cdr state)) - (if (consp containing-sexp) - ;; if cdr == point, then containing sexp is the brace - ;; that opens the sexp we close - (if (= (cdr containing-sexp) (point)) - (setq containing-sexp (car containing-sexp)) - ;; otherwise, ignore this element - (setq containing-sexp nil)) - ;; ignore the bufpos if its been narrowed out by the - ;; containing class - (if (<= containing-sexp (point-min)) - (setq containing-sexp nil))))) - - ;; set the limit on the farthest back we need to search - (setq lim (or containing-sexp - (if (consp (car fullstate)) - (cdr (car fullstate)) - nil) - (point-min))) - - ;; cache char before and after indent point, and move point to - ;; the most likely position to perform the majority of tests - (goto-char indent-point) - (skip-chars-forward " \t") - (setq char-after-ip (char-after)) - (c-backward-syntactic-ws lim) - (setq char-before-ip (char-before)) - (goto-char indent-point) - (skip-chars-forward " \t") - - ;; are we in a literal? - (setq literal (c-in-literal lim)) - - ;; now figure out syntactic qualities of the current line - (cond - ;; CASE 1: in a string. - ((memq literal '(string)) - (c-add-syntax 'string (c-point 'bopl))) - ;; CASE 2: in a C or C++ style comment. - ((memq literal '(c c++)) - ;; we need to catch multi-paragraph C comments - (while (and (zerop (forward-line -1)) - (looking-at "^[ \t]*$"))) - (c-add-syntax literal (c-point 'boi))) - ;; CASE 3: in a cpp preprocessor - ((eq literal 'pound) - (c-beginning-of-macro lim) - (c-add-syntax 'cpp-macro (c-point 'boi))) - ;; CASE 4: in an objective-c method intro - (in-method-intro-p - (c-add-syntax 'objc-method-intro (c-point 'boi))) - ;; CASE 5: Line is at top level. - ((null containing-sexp) - (cond - ;; CASE 5A: we are looking at a defun, class, or - ;; inline-inclass method opening brace - ((eq char-after-ip ?{) - (cond - ;; CASE 5A.1: extern declaration - ((save-excursion - (goto-char indent-point) - (skip-chars-forward " \t") - (and (c-safe (progn (backward-sexp 2) t)) - (looking-at "extern[^_]") - (progn - (setq placeholder (point)) - (forward-sexp 1) - (c-forward-syntactic-ws) - (eq (char-after) ?\")))) - (goto-char placeholder) - (c-add-syntax 'extern-lang-open (c-point 'boi))) - ;; CASE 5A.2: we are looking at a class opening brace - ((save-excursion - (goto-char indent-point) - (skip-chars-forward " \t{") - ;; TBD: watch out! there could be a bogus - ;; c-state-cache in place when we get here. we have - ;; to go through much chicanery to ignore the cache. - ;; But of course, there may not be! BLECH! BOGUS! - (let ((decl - (if (boundp 'c-state-cache) - (let ((old-cache c-state-cache)) - (prog2 - (makunbound 'c-state-cache) - (c-search-uplist-for-classkey (c-parse-state)) - (setq c-state-cache old-cache))) - (c-search-uplist-for-classkey (c-parse-state)) - ))) - (and decl - (setq placeholder (aref decl 0))) - )) - (c-add-syntax 'class-open placeholder)) - ;; CASE 5A.3: brace list open - ((save-excursion - (c-beginning-of-statement-1 lim) - ;; c-b-o-s could have left us at point-min - (and (bobp) - (c-forward-syntactic-ws indent-point)) - (if (looking-at "typedef[^_]") - (progn (forward-sexp 1) - (c-forward-syntactic-ws indent-point))) - (setq placeholder (c-point 'boi)) - (and (or (looking-at "enum[ \t\n]+") - (eq char-before-ip ?=)) - (save-excursion - (skip-chars-forward "^;(" indent-point) - (not (memq (char-after) '(?\; ?\())) - ))) - (c-add-syntax 'brace-list-open placeholder)) - ;; CASE 5A.4: inline defun open - ((and inclass-p (not inextern-p)) - (c-add-syntax 'inline-open) - (c-add-syntax 'inclass (aref inclass-p 0))) - ;; CASE 5A.5: ordinary defun open - (t - (goto-char placeholder) - (c-add-syntax 'defun-open (c-point 'bol)) - ))) - ;; CASE 5B: first K&R arg decl or member init - ((c-just-after-func-arglist-p) - (cond - ;; CASE 5B.1: a member init - ((or (eq char-before-ip ?:) - (eq char-after-ip ?:)) - ;; this line should be indented relative to the beginning - ;; of indentation for the topmost-intro line that contains - ;; the prototype's open paren - ;; TBD: is the following redundant? - (if (eq char-before-ip ?:) - (forward-char -1)) - (c-backward-syntactic-ws lim) - ;; TBD: is the preceding redundant? - (if (eq (char-before) ?:) - (progn (forward-char -1) - (c-backward-syntactic-ws lim))) - (if (eq (char-before) ?\)) - (backward-sexp 1)) - (setq placeholder (point)) - (save-excursion - (and (c-safe (backward-sexp 1) t) - (looking-at "throw[^_]") - (c-safe (backward-sexp 1) t) - (setq placeholder (point)))) - (goto-char placeholder) - (c-add-syntax 'member-init-intro (c-point 'boi)) - ;; we don't need to add any class offset since this - ;; should be relative to the ctor's indentation - ) - ;; CASE 5B.2: K&R arg decl intro - (c-recognize-knr-p - (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) - (and inclass-p (c-add-syntax 'inclass (aref inclass-p 0)))) - ;; CASE 5B.3: Nether region after a C++ or Java func - ;; decl, which could include a `throws' declaration. - (t - (c-beginning-of-statement-1 lim) - (c-add-syntax 'func-decl-cont (c-point 'boi)) - ))) - ;; CASE 5C: inheritance line. could be first inheritance - ;; line, or continuation of a multiple inheritance - ((or (and c-baseclass-key (looking-at c-baseclass-key)) - (and (or (eq char-before-ip ?:) - ;; watch out for scope operator - (save-excursion - (and (eq char-after-ip ?:) - (c-safe (progn (forward-char 1) t)) - (not (eq (char-after) ?:)) - ))) - (save-excursion - (c-backward-syntactic-ws lim) - (if (eq char-before-ip ?:) - (progn - (forward-char -1) - (c-backward-syntactic-ws lim))) - (back-to-indentation) - (looking-at c-class-key))) - ;; for Java - (and (eq major-mode 'java-mode) - (let ((fence (save-excursion - (c-beginning-of-statement-1 lim) - (point))) - cont done) - (save-excursion - (while (not done) - (cond ((looking-at c-Java-special-key) - (setq injava-inher (cons cont (point)) - done t)) - ((or (not (c-safe (forward-sexp -1) t)) - (<= (point) fence)) - (setq done t)) - ) - (setq cont t))) - injava-inher) - (not (c-crosses-statement-barrier-p (cdr injava-inher) - (point))) - )) - (cond - ;; CASE 5C.1: non-hanging colon on an inher intro - ((eq char-after-ip ?:) - (c-backward-syntactic-ws lim) - (c-add-syntax 'inher-intro (c-point 'boi)) - ;; don't add inclass symbol since relative point already - ;; contains any class offset - ) - ;; CASE 5C.2: hanging colon on an inher intro - ((eq char-before-ip ?:) - (c-add-syntax 'inher-intro (c-point 'boi)) - (and inclass-p (c-add-syntax 'inclass (aref inclass-p 0)))) - ;; CASE 5C.3: in a Java implements/extends - (injava-inher - (let ((where (cdr injava-inher)) - (cont (car injava-inher))) - (goto-char where) - (cond ((looking-at "throws[ \t\n]") - (c-add-syntax 'func-decl-cont - (progn (c-beginning-of-statement-1 lim) - (c-point 'boi)))) - (cont (c-add-syntax 'inher-cont where)) - (t (c-add-syntax 'inher-intro - (progn (goto-char (cdr injava-inher)) - (c-beginning-of-statement-1 lim) - (point)))) - ))) - ;; CASE 5C.4: a continued inheritance line - (t - (c-beginning-of-inheritance-list lim) - (c-add-syntax 'inher-cont (point)) - ;; don't add inclass symbol since relative point already - ;; contains any class offset - ))) - ;; CASE 5D: this could be a top-level compound statement or a - ;; member init list continuation - ((eq char-before-ip ?,) - (goto-char indent-point) - (c-backward-syntactic-ws lim) - (while (and (< lim (point)) - (eq (char-before) ?,)) - ;; this will catch member inits with multiple - ;; line arglists - (forward-char -1) - (c-backward-syntactic-ws (c-point 'bol)) - (if (eq (char-before) ?\)) - (backward-sexp 1)) - ;; now continue checking - (beginning-of-line) - (c-backward-syntactic-ws lim)) - (cond - ;; CASE 5D.1: hanging member init colon, but watch out - ;; for bogus matches on access specifiers inside classes. - ((and (eq (char-before) ?:) - (save-excursion - (forward-word -1) - (not (looking-at c-access-key)))) - (goto-char indent-point) - (c-backward-syntactic-ws lim) - (c-safe (backward-sexp 1)) - (c-add-syntax 'member-init-cont (c-point 'boi)) - ;; we do not need to add class offset since relative - ;; point is the member init above us - ) - ;; CASE 5D.2: non-hanging member init colon - ((progn - (c-forward-syntactic-ws indent-point) - (eq (char-after) ?:)) - (skip-chars-forward " \t:") - (c-add-syntax 'member-init-cont (point))) - ;; CASE 5D.3: perhaps a multiple inheritance line? - ((looking-at c-inher-key) - (c-add-syntax 'inher-cont (c-point 'boi))) - ;; CASE 5D.4: perhaps a template list continuation? - ((save-excursion - (goto-char indent-point) - (skip-chars-backward "^<" lim) - ;; not sure if this is the right test, but it should - ;; be fast and mostly accurate. - (and (eq (char-before) ?<) - (not (c-in-literal lim)))) - ;; we can probably indent it just like an arglist-cont - (c-add-syntax 'template-args-cont (point))) - ;; CASE 5D.5: perhaps a top-level statement-cont - (t - (c-beginning-of-statement-1 lim) - ;; skip over any access-specifiers - (and inclass-p c-access-key - (while (looking-at c-access-key) - (forward-line 1))) - ;; skip over comments, whitespace - (c-forward-syntactic-ws indent-point) - (c-add-syntax 'statement-cont (c-point 'boi))) - )) - ;; CASE 5E: we are looking at a access specifier - ((and inclass-p - c-access-key - (looking-at c-access-key)) - (c-add-syntax 'access-label (c-point 'bonl)) - (c-add-syntax 'inclass (aref inclass-p 0))) - ;; CASE 5F: extern-lang-close? - ((and inextern-p - (eq char-after-ip ?})) - (c-add-syntax 'extern-lang-close (aref inclass-p 0))) - ;; CASE 5G: we are looking at the brace which closes the - ;; enclosing nested class decl - ((and inclass-p - (eq char-after-ip ?}) - (save-excursion - (save-restriction - (widen) - (forward-char 1) - (and - (condition-case nil - (progn (backward-sexp 1) t) - (error nil)) - (= (point) (aref inclass-p 1)) - )))) - (save-restriction - (widen) - (goto-char (aref inclass-p 0)) - (c-add-syntax 'class-close (c-point 'boi)))) - ;; CASE 5H: we could be looking at subsequent knr-argdecls - ((and c-recognize-knr-p - ;; here we essentially use the hack that is used in - ;; Emacs' c-mode.el to limit how far back we should - ;; look. The assumption is made that argdecls are - ;; indented at least one space and that function - ;; headers are not indented. - (let ((limit (save-excursion - (re-search-backward "^[^ \^L\t\n#]" nil 'move) - (point)))) - (save-excursion - (c-backward-syntactic-ws limit) - (setq placeholder (point)) - (while (and (memq (char-before) '(?\; ?,)) - (> (point) limit)) - (beginning-of-line) - (setq placeholder (point)) - (c-backward-syntactic-ws limit)) - (and (eq (char-before) ?\)) - (or (not c-method-key) - (progn - (forward-sexp -1) - (forward-char -1) - (c-backward-syntactic-ws) - (not (or (memq (char-before) '(?- ?+)) - ;; or a class category - (progn - (forward-sexp -2) - (looking-at c-class-key)) - ))))) - )) - (save-excursion - (c-beginning-of-statement-1) - (not (looking-at "typedef[ \t\n]+")))) - (goto-char placeholder) - (c-add-syntax 'knr-argdecl (c-point 'boi))) - ;; CASE 5I: we are at the topmost level, make sure we skip - ;; back past any access specifiers - ((progn - (c-backward-syntactic-ws lim) - (while (and inclass-p - c-access-key - (not (bobp)) - (save-excursion - (c-safe (progn (backward-sexp 1) t)) - (looking-at c-access-key))) - (backward-sexp 1) - (c-backward-syntactic-ws lim)) - (or (bobp) - (memq (char-before) '(?\; ?\})))) - ;; real beginning-of-line could be narrowed out due to - ;; enclosure in a class block - (save-restriction - (widen) - (c-add-syntax 'topmost-intro (c-point 'bol)) - (if inclass-p - (progn - (goto-char (aref inclass-p 1)) - (or (= (point) (c-point 'boi)) - (goto-char (aref inclass-p 0))) - (if inextern-p - (c-add-syntax 'inextern-lang) - (c-add-syntax 'inclass (c-point 'boi))))) - )) - ;; CASE 5J: we are at an ObjC or Java method definition - ;; continuation line. - ((and c-method-key - (progn - (c-beginning-of-statement-1 lim) - (beginning-of-line) - (looking-at c-method-key))) - (c-add-syntax 'objc-method-args-cont (point))) - ;; CASE 5K: we are at a topmost continuation line - (t - (c-beginning-of-statement-1 lim) - (c-forward-syntactic-ws) - (c-add-syntax 'topmost-intro-cont (c-point 'boi))) - )) ; end CASE 5 - ;; CASE 6: line is an expression, not a statement. Most - ;; likely we are either in a function prototype or a function - ;; call argument list - ((not (eq (char-after containing-sexp) ?{)) - (c-backward-syntactic-ws containing-sexp) - (cond - ;; CASE 6A: we are looking at the arglist closing paren - ((and (not (eq char-before-ip ?,)) - (memq char-after-ip '(?\) ?\]))) - (goto-char containing-sexp) - (c-add-syntax 'arglist-close (c-point 'boi))) - ;; CASE 6B: we are looking at the first argument in an empty - ;; argument list. Use arglist-close if we're actually - ;; looking at a close paren or bracket. - ((memq char-before-ip '(?\( ?\[)) - (goto-char containing-sexp) - (c-add-syntax 'arglist-intro (c-point 'boi))) - ;; CASE 6C: we are inside a conditional test clause. treat - ;; these things as statements - ((save-excursion - (goto-char containing-sexp) - (and (c-safe (progn (forward-sexp -1) t)) - (looking-at "\\[^_]"))) - (goto-char (1+ containing-sexp)) - (c-forward-syntactic-ws indent-point) - (c-beginning-of-statement-1 containing-sexp) - (if (eq char-before-ip ?\;) - (c-add-syntax 'statement (point)) - (c-add-syntax 'statement-cont (point)) - )) - ;; CASE 6D: maybe a continued method call. This is the case - ;; when we are inside a [] bracketed exp, and what precede - ;; the opening bracket is not an identifier. - ((and c-method-key - (eq (char-after containing-sexp) ?\[) - (save-excursion - (goto-char (1- containing-sexp)) - (c-backward-syntactic-ws (c-point 'bod)) - (if (not (looking-at c-symbol-key)) - (c-add-syntax 'objc-method-call-cont containing-sexp)) - ))) - ;; CASE 6E: we are looking at an arglist continuation line, - ;; but the preceding argument is on the same line as the - ;; opening paren. This case includes multi-line - ;; mathematical paren groupings, but we could be on a - ;; for-list continuation line - ((and (save-excursion - (goto-char (1+ containing-sexp)) - (skip-chars-forward " \t") - (not (eolp))) - (save-excursion - (c-beginning-of-statement-1 lim) - (skip-chars-backward " \t([") - (<= (point) containing-sexp))) - (goto-char containing-sexp) - (c-add-syntax 'arglist-cont-nonempty (c-point 'boi))) - ;; CASE 6F: we are looking at just a normal arglist - ;; continuation line - (t (c-beginning-of-statement-1 containing-sexp) - (forward-char 1) - (c-forward-syntactic-ws indent-point) - (c-add-syntax 'arglist-cont (c-point 'boi))) - )) - ;; CASE 7: func-local multi-inheritance line - ((and c-baseclass-key - (save-excursion - (goto-char indent-point) - (skip-chars-forward " \t") - (looking-at c-baseclass-key))) - (goto-char indent-point) - (skip-chars-forward " \t") - (cond - ;; CASE 7A: non-hanging colon on an inher intro - ((eq char-after-ip ?:) - (c-backward-syntactic-ws lim) - (c-add-syntax 'inher-intro (c-point 'boi))) - ;; CASE 7B: hanging colon on an inher intro - ((eq char-before-ip ?:) - (c-add-syntax 'inher-intro (c-point 'boi))) - ;; CASE 7C: a continued inheritance line - (t - (c-beginning-of-inheritance-list lim) - (c-add-syntax 'inher-cont (point)) - ))) - ;; CASE 8: we are inside a brace-list - ((setq placeholder (c-inside-bracelist-p containing-sexp state)) - (cond - ;; CASE 8A: brace-list-close brace - ((and (eq char-after-ip ?}) - (c-safe (progn (forward-char 1) - (backward-sexp 1) - t)) - (= (point) containing-sexp)) - (c-add-syntax 'brace-list-close (c-point 'boi))) - ;; CASE 8B: we're looking at the first line in a brace-list - ((save-excursion - (goto-char indent-point) - (c-backward-syntactic-ws containing-sexp) - (= (point) (1+ containing-sexp))) - (goto-char containing-sexp) - (c-add-syntax 'brace-list-intro (c-point 'boi)) - ) - ;;)) ; end CASE 8B - ;; CASE 8C: this is just a later brace-list-entry - (t (goto-char (1+ containing-sexp)) - (c-forward-syntactic-ws indent-point) - (if (eq char-after-ip ?{) - (c-add-syntax 'brace-list-open (point)) - (c-add-syntax 'brace-list-entry (point)) - )) ; end CASE 8C - )) ; end CASE 8 - ;; CASE 9: A continued statement - ((and (not (memq char-before-ip '(?\; ?} ?:))) - (> (point) - (save-excursion - (c-beginning-of-statement-1 containing-sexp) - (setq placeholder (point)))) - (/= placeholder containing-sexp)) - (goto-char indent-point) - (skip-chars-forward " \t") - (let ((after-cond-placeholder - (save-excursion - (goto-char placeholder) - (if (looking-at c-conditional-key) - (progn - (c-safe (c-skip-conditional)) - (c-forward-syntactic-ws) - (if (eq (char-after) ?\;) - (progn - (forward-char 1) - (c-forward-syntactic-ws))) - (point)) - nil)))) - (cond - ;; CASE 9A: substatement - ((and after-cond-placeholder - (>= after-cond-placeholder indent-point)) - (goto-char placeholder) - (if (eq char-after-ip ?{) - (c-add-syntax 'substatement-open (c-point 'boi)) - (c-add-syntax 'substatement (c-point 'boi)))) - ;; CASE 9B: open braces for class or brace-lists - ((eq char-after-ip ?{) - (cond - ;; CASE 9B.1: class-open - ((save-excursion - (goto-char indent-point) - (skip-chars-forward " \t{") - (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) - (and decl - (setq placeholder (aref decl 0))) - )) - (c-add-syntax 'class-open placeholder)) - ;; CASE 9B.2: brace-list-open - ((or (save-excursion - (goto-char placeholder) - (looking-at "\\")) - (eq char-before-ip ?=)) - (c-add-syntax 'brace-list-open placeholder)) - ;; CASE 9B.3: catch-all for unknown construct. - (t - ;; Can and should I add an extensibility hook here? - ;; Something like c-recognize-hook so support for - ;; unknown constructs could be added. It's probably a - ;; losing proposition, so I dunno. - (goto-char placeholder) - (c-add-syntax 'statement-cont (c-point 'boi)) - (c-add-syntax 'block-open)) - )) - ;; CASE 9C: iostream insertion or extraction operator - ((looking-at "<<\\|>>") - (goto-char placeholder) - (and after-cond-placeholder - (goto-char after-cond-placeholder)) - (while (and (re-search-forward "<<\\|>>" indent-point 'move) - (c-in-literal placeholder))) - ;; if we ended up at indent-point, then the first - ;; streamop is on a separate line. Indent the line like - ;; a statement-cont instead - (if (/= (point) indent-point) - (c-add-syntax 'stream-op (c-point 'boi)) - (c-backward-syntactic-ws lim) - (c-add-syntax 'statement-cont (c-point 'boi)))) - ;; CASE 9D: continued statement. find the accurate - ;; beginning of statement or substatement - (t - (c-beginning-of-statement-1 after-cond-placeholder) - ;; KLUDGE ALERT! c-beginning-of-statement-1 can leave - ;; us before the lim we're passing in. It should be - ;; fixed, but I'm worried about side-effects at this - ;; late date. Fix for v5. - (goto-char (or (and after-cond-placeholder - (max after-cond-placeholder (point))) - (point))) - (c-add-syntax 'statement-cont (point))) - ))) - ;; CASE 10: an else clause? - ((looking-at "\\[^_]") - (c-backward-to-start-of-if containing-sexp) - (c-add-syntax 'else-clause (c-point 'boi))) - ;; CASE 11: Statement. But what kind? Lets see if its a - ;; while closure of a do/while construct - ((progn - (goto-char indent-point) - (skip-chars-forward " \t") - (and (looking-at "while\\b[^_]") - (save-excursion - (c-backward-to-start-of-do containing-sexp) - (setq placeholder (point)) - (looking-at "do\\b[^_]")) - )) - (c-add-syntax 'do-while-closure placeholder)) - ;; CASE 12: A case or default label - ((looking-at c-switch-label-key) - (goto-char containing-sexp) - ;; check for hanging braces - (if (/= (point) (c-point 'boi)) - (forward-sexp -1)) - (c-add-syntax 'case-label (c-point 'boi))) - ;; CASE 13: any other label - ((looking-at c-label-key) - (goto-char containing-sexp) - (c-add-syntax 'label (c-point 'boi))) - ;; CASE 14: block close brace, possibly closing the defun or - ;; the class - ((eq char-after-ip ?}) - (let* ((lim (c-safe-position containing-sexp fullstate)) - (relpos (save-excursion - (goto-char containing-sexp) - (if (/= (point) (c-point 'boi)) - (c-beginning-of-statement-1 lim)) - (c-point 'boi)))) - (cond - ;; CASE 14A: does this close an inline? - ((let ((inclass-p (progn - (goto-char containing-sexp) - (c-search-uplist-for-classkey state)))) - ;; inextern-p in higher level let* - (setq inextern-p (and inclass-p - (progn - (goto-char (aref inclass-p 0)) - (looking-at "extern[^_]")))) - (and inclass-p (not inextern-p))) - (c-add-syntax 'inline-close relpos)) - ;; CASE 14B: if there an enclosing brace that hasn't - ;; been narrowed out by a class, then this is a - ;; block-close - ((and (not inextern-p) - (c-most-enclosing-brace state)) - (c-add-syntax 'block-close relpos)) - ;; CASE 14C: find out whether we're closing a top-level - ;; class or a defun - (t - (save-restriction - (narrow-to-region (point-min) indent-point) - (let ((decl (c-search-uplist-for-classkey (c-parse-state)))) - (if decl - (c-add-syntax 'class-close (aref decl 0)) - (c-add-syntax 'defun-close relpos))))) - ))) - ;; CASE 15: statement catchall - (t - ;; we know its a statement, but we need to find out if it is - ;; the first statement in a block - (goto-char containing-sexp) - (forward-char 1) - (c-forward-syntactic-ws indent-point) - ;; now skip forward past any case/default clauses we might find. - (while (or (c-skip-case-statement-forward fullstate indent-point) - (and (looking-at c-switch-label-key) - (not inswitch-p))) - (setq inswitch-p t)) - ;; we want to ignore non-case labels when skipping forward - (while (and (looking-at c-label-key) - (goto-char (match-end 0))) - (c-forward-syntactic-ws indent-point)) - (cond - ;; CASE 15A: we are inside a case/default clause inside a - ;; switch statement. find out if we are at the statement - ;; just after the case/default label. - ((and inswitch-p - (progn - (goto-char indent-point) - (c-backward-syntactic-ws containing-sexp) - (back-to-indentation) - (setq placeholder (point)) - (looking-at c-switch-label-key))) - (goto-char indent-point) - (skip-chars-forward " \t") - (if (eq (char-after) ?{) - (c-add-syntax 'statement-case-open placeholder) - (c-add-syntax 'statement-case-intro placeholder))) - ;; CASE 15B: continued statement - ((eq char-before-ip ?,) - (c-add-syntax 'statement-cont (c-point 'boi))) - ;; CASE 15C: a question/colon construct? But make sure - ;; what came before was not a label, and what comes after - ;; is not a globally scoped function call! - ((or (and (memq char-before-ip '(?: ??)) - (save-excursion - (goto-char indent-point) - (c-backward-syntactic-ws lim) - (back-to-indentation) - (not (looking-at c-label-key)))) - (and (memq char-after-ip '(?: ??)) - (save-excursion - (goto-char indent-point) - (skip-chars-forward " \t") - ;; watch out for scope operator - (not (looking-at "::"))))) - (c-add-syntax 'statement-cont (c-point 'boi))) - ;; CASE 15D: any old statement - ((< (point) indent-point) - (let ((safepos (c-most-enclosing-brace fullstate)) - relpos done) - (goto-char indent-point) - (c-beginning-of-statement-1 safepos) - ;; It is possible we're on the brace that opens a nested - ;; function. - (if (and (eq (char-after) ?{) - (save-excursion - (c-backward-syntactic-ws safepos) - (not (eq (char-before) ?\;)))) - (c-beginning-of-statement-1 safepos)) - (if (and inswitch-p - (looking-at c-switch-label-key)) - (progn - (goto-char placeholder) - (end-of-line) - (forward-sexp -1))) - (setq relpos (c-point 'boi)) - (while (and (not done) - (<= safepos (point)) - (/= relpos (point))) - (c-beginning-of-statement-1 safepos) - (if (= relpos (c-point 'boi)) - (setq done t)) - (setq relpos (c-point 'boi))) - (c-add-syntax 'statement relpos) - (if (eq char-after-ip ?{) - (c-add-syntax 'block-open)))) - ;; CASE 15E: first statement in an inline, or first - ;; statement in a top-level defun. we can tell this is it - ;; if there are no enclosing braces that haven't been - ;; narrowed out by a class (i.e. don't use bod here!) - ((save-excursion - (save-restriction - (widen) - (goto-char containing-sexp) - (c-narrow-out-enclosing-class state containing-sexp) - (not (c-most-enclosing-brace state)))) - (goto-char containing-sexp) - ;; if not at boi, then defun-opening braces are hung on - ;; right side, so we need a different relpos - (if (/= (point) (c-point 'boi)) - (progn - (c-backward-syntactic-ws) - (c-safe (forward-sexp (if (eq (char-before) ?\)) - -1 -2))) - ;; looking at a Java throws clause following a - ;; method's parameter list - (c-beginning-of-statement-1) - )) - (c-add-syntax 'defun-block-intro (c-point 'boi))) - ;; CASE 15F: first statement in a block - (t (goto-char containing-sexp) - (if (/= (point) (c-point 'boi)) - (c-beginning-of-statement-1 - (if (= (point) lim) - (c-safe-position (point) state) lim))) - (c-add-syntax 'statement-block-intro (c-point 'boi)) - (if (eq char-after-ip ?{) - (c-add-syntax 'block-open))) - )) - ) - - ;; now we need to look at any modifiers - (goto-char indent-point) - (skip-chars-forward " \t") - ;; are we looking at a comment only line? - (if (looking-at c-comment-start-regexp) - (c-add-syntax 'comment-intro)) - ;; we might want to give additional offset to friends (in C++). - (if (and (eq major-mode 'c++-mode) - (looking-at c-C++-friend-key)) - (c-add-syntax 'friend)) - ;; return the syntax - syntax)))) - - -(defun c-echo-parsing-error () - (if (not c-parsing-error) - nil - (message "unbalanced close brace at bufpos %d -- INDENTATION IS SUSPECT!" - c-parsing-error) - (ding)) - c-parsing-error) - -;; indent via syntactic language elements -(defun c-indent-line (&optional syntax) - ;; indent the current line as C/C++/ObjC code. Optional SYNTAX is the - ;; syntactic information for the current line. Returns the amount of - ;; indentation change - (let* ((c-syntactic-context (or syntax (c-guess-basic-syntax))) - (pos (- (point-max) (point))) - (indent (apply '+ (mapcar 'c-get-offset c-syntactic-context))) - (shift-amt (- (current-indentation) indent))) - (and c-echo-syntactic-information-p - (not (c-echo-parsing-error)) - (message "syntax: %s, indent= %d" c-syntactic-context indent)) - (if (zerop shift-amt) - nil - (delete-region (c-point 'bol) (c-point 'boi)) - (beginning-of-line) - (indent-to indent)) - (if (< (point) (c-point 'boi)) - (back-to-indentation) - ;; If initial point was within line's indentation, position after - ;; the indentation. Else stay at same point in text. - (if (> (- (point-max) pos) (point)) - (goto-char (- (point-max) pos))) - ) - (run-hooks 'c-special-indent-hook) - shift-amt)) - -(defun c-show-syntactic-information (arg) - "Show syntactic information for current line. -With universal argument, inserts the analysis as a comment on that line." - (interactive "P") - (let ((syntax (c-guess-basic-syntax))) - (if (not (consp arg)) - (if (not (c-echo-parsing-error)) - (message "syntactic analysis: %s" syntax)) - (indent-for-comment) - (insert (format "%s" syntax)) - )) - (c-keep-region-active)) - - -(provide 'cc-engine) -;;; cc-engine.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-langs.el --- a/lisp/cc-mode/cc-langs.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,563 +0,0 @@ -;;; cc-langs.el --- specific language support for CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -(require 'cc-defs) - - -;; Regular expressions and other values which must be parameterized on -;; a per-language basis. - -;; Keywords defining protection levels -(defconst c-protection-key "\\<\\(public\\|protected\\|private\\)\\>") - -;; Regex describing a `symbol' in all languages. We cannot use just -;; `word' syntax class since `_' cannot be in word class. Putting -;; underscore in word class breaks forward word movement behavior that -;; users are familiar with. Besides, this runs counter to Emacs -;; convention. -;; -;; I suspect this definition isn't correct in light of Java's -;; definition of a symbol as being Unicode. I know so little about -;; I18N (except how to sound cool and say I18N :-) that I'm willing to -;; punt on this for now. - -(defconst c-symbol-key "[_a-zA-Z]\\(\\w\\|\\s_\\)*") - - -;; keywords introducing class definitions. language specific -(defconst c-C-class-key "\\(struct\\|union\\)") -(defconst c-C++-class-key "\\(class\\|struct\\|union\\)") - -(defconst c-ObjC-class-key - (concat - "@\\(interface\\|implementation\\)\\s +" - c-symbol-key ;name of the class - "\\(\\s *:\\s *" c-symbol-key "\\)?" ;maybe followed by the superclass - "\\(\\s *<[^>]+>\\)?" ;and maybe the adopted protocols list - )) - -(defconst c-Java-class-key - (concat - "\\(" c-protection-key "\\s +\\)?" - "\\(interface\\|class\\)\\s +" - c-symbol-key ;name of the class - "\\(\\s *extends\\s *" c-symbol-key "\\)?" ;maybe followed by superclass - ;;"\\(\\s *implements *[^{]+{\\)?" ;maybe the adopted protocols list - )) - -(defvar c-class-key c-C-class-key) -(make-variable-buffer-local 'c-class-key) - - -;; regexp describing access protection clauses. language specific -(defvar c-access-key nil) -(make-variable-buffer-local 'c-access-key) -(defconst c-C++-access-key (concat c-protection-key "[ \t]*:")) -(defconst c-ObjC-access-key (concat "@" c-protection-key)) -(defconst c-Java-access-key nil) - - -;; keywords introducing conditional blocks -(defconst c-C-conditional-key nil) -(defconst c-C++-conditional-key nil) -(defconst c-Java-conditional-key nil) - -(let ((all-kws "for\\|if\\|do\\|else\\|while\\|switch") - (exc-kws "\\|try\\|catch") - (thr-kws "\\|finally\\|synchronized") - (front "\\b\\(") - (back "\\)\\b[^_]")) - (setq c-C-conditional-key (concat front all-kws back) - c-C++-conditional-key (concat front all-kws exc-kws back) - c-Java-conditional-key (concat front all-kws exc-kws thr-kws back))) - -(defvar c-conditional-key c-C-conditional-key) -(make-variable-buffer-local 'c-conditional-key) - - -;; keywords describing method definition introductions -(defvar c-method-key nil) -(make-variable-buffer-local 'c-method-key) - -(defconst c-ObjC-method-key - (concat - "^\\s *[+-]\\s *" - "\\(([^)]*)\\)?" ; return type - ;; \\s- in objc syntax table does not include \n - ;; since it is considered the end of //-comments. - "[ \t\n]*" c-symbol-key)) - -(defconst c-Java-method-key - (concat - "^\\s *[+-]\\s *" - "\\(([^)]*)\\)?" ; return type - ;; \\s- in java syntax table does not include \n - ;; since it is considered the end of //-comments. - "[ \t\n]*" c-symbol-key)) - - -;; comment starter definitions for various languages. language specific -(defconst c-C++-comment-start-regexp "/[/*]") -;; We need to match all 3 Java style comments -;; 1) Traditional C block; 2) javadoc /** ...; 3) C++ style -(defconst c-Java-comment-start-regexp "/\\(/\\|[*][*]?\\)") -(defvar c-comment-start-regexp c-C++-comment-start-regexp) -(make-variable-buffer-local 'c-comment-start-regexp) - - - -;; Regexp describing a switch's case or default label for all languages -(defconst c-switch-label-key "\\(\\(case[( \t]+\\S .*\\)\\|default[ \t]*\\):") -;; Regexp describing any label. -(defconst c-label-key (concat c-symbol-key ":\\([^:]\\|$\\)")) - -;; Regexp describing class inheritance declarations. TBD: this should -;; be language specific, and only makes sense for C++ -(defconst c-inher-key - (concat "\\(\\\\s +\\)?" - c-C++-class-key "[ \t]+" c-symbol-key - "\\([ \t]*:[ \t]*\\)\\s *[^;]")) - -;; Regexp describing C++ base classes in a derived class definition. -;; TBD: this should be language specific, and only makes sense for C++ -(defvar c-baseclass-key - (concat - ":?[ \t]*\\(virtual[ \t]+\\)?\\(" - c-protection-key "[ \t]+\\)" c-symbol-key)) -(make-variable-buffer-local 'c-baseclass-key) - -;; Regexp describing friend declarations in C++ classes. -(defconst c-C++-friend-key - "friend[ \t]+\\|template[ \t]*<.+>[ \t]*friend[ \t]+") - -;; Regexp describing Java inheritance and throws clauses. -(defconst c-Java-special-key "\\(implements\\|extends\\|throws\\)[^_]") - -;; Regexp describing the beginning of a Java top-level definition. -(defconst c-Java-defun-prompt-regexp - "^[ \t]*\\(\\(\\(public\\|protected\\|private\\|const\\|abstract\\|synchronized\\|final\\|static\\|threadsafe\\|transient\\|native\\|volatile\\)\\s-+\\)*\\(\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*[][_$.a-zA-Z0-9]+\\|[[a-zA-Z]\\)\\s-*\\)\\s-+\\)\\)?\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*\\s-+\\)\\s-*\\)?\\([_a-zA-Z][^][ \t:;.,{}()=]*\\|\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)\\)\\s-*\\(([^);{}]*)\\)?\\([] \t]*\\)\\(\\s-*\\\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f]*\\)+\\)?\\s-*") - - - -;; internal state variables - -;; Internal state of hungry delete key feature -(defvar c-hungry-delete-key nil) -(make-variable-buffer-local 'c-hungry-delete-key) - -;; Internal state of auto newline feature. -(defvar c-auto-newline nil) -(make-variable-buffer-local 'c-auto-newline) - -;; Internal auto-newline/hungry-delete designation string for mode line. -(defvar c-auto-hungry-string nil) -(make-variable-buffer-local 'c-auto-hungry-string) - -;; Non-nil means K&R style argument declarations are valid. -(defvar c-recognize-knr-p t) -(make-variable-buffer-local 'c-recognize-knr-p) - - - -(defun c-use-java-style () - "Institutes `java' indentation style. -For use with the variable `java-mode-hook'." - (c-set-style "java")) - -(defun c-common-init () - ;; Common initializations for all modes. - ;; these variables should always be buffer local; they do not affect - ;; indentation style. - (make-local-variable 'paragraph-start) - (make-local-variable 'paragraph-separate) - (make-local-variable 'paragraph-ignore-fill-prefix) - (make-local-variable 'require-final-newline) - (make-local-variable 'parse-sexp-ignore-comments) - (make-local-variable 'indent-line-function) - (make-local-variable 'indent-region-function) - (make-local-variable 'comment-start) - (make-local-variable 'comment-end) - (make-local-variable 'comment-column) - (make-local-variable 'comment-start-skip) - (make-local-variable 'comment-multi-line) - (make-local-variable 'outline-regexp) - (make-local-variable 'outline-level) - (make-local-variable 'adaptive-fill-regexp) - (make-local-variable 'imenu-generic-expression) ;set in the mode functions - ;; X/Emacs 20 only - (and (boundp 'comment-line-break-function) - (make-local-variable 'comment-line-break-function)) - ;; Emacs 19.30 and beyond only, AFAIK - (if (boundp 'fill-paragraph-function) - (progn - (make-local-variable 'fill-paragraph-function) - (setq fill-paragraph-function 'c-fill-paragraph))) - ;; now set their values - (setq paragraph-start (concat page-delimiter "\\|$") - paragraph-separate paragraph-start - paragraph-ignore-fill-prefix t - require-final-newline t - parse-sexp-ignore-comments t - indent-line-function 'c-indent-line - indent-region-function 'c-indent-region - outline-regexp "[^#\n\^M]" - outline-level 'c-outline-level - comment-column 32 - comment-start-skip "/\\*+ *\\|// *" - comment-multi-line nil - comment-line-break-function 'c-comment-line-break-function - adaptive-fill-regexp nil) - ;; we have to do something special for c-offsets-alist so that the - ;; buffer local value has its own alist structure. - (setq c-offsets-alist (copy-alist c-offsets-alist)) - ;; setup the comment indent variable in a Emacs version portable way - ;; ignore any byte compiler warnings you might get here - (make-local-variable 'comment-indent-function) - (setq comment-indent-function 'c-comment-indent) - ;; add menus to menubar - (easy-menu-add (c-mode-menu mode-name)) - ;; put auto-hungry designators onto minor-mode-alist, but only once - (or (assq 'c-auto-hungry-string minor-mode-alist) - (setq minor-mode-alist - (cons '(c-auto-hungry-string c-auto-hungry-string) - minor-mode-alist)))) - -(defun c-postprocess-file-styles () - "Function that post processes relevant file local variables. -Currently, this function simply applies any style and offset settings -found in the file's Local Variable list. It first applies any style -setting found in `c-file-style', then it applies any offset settings -it finds in `c-file-offsets'." - ;; apply file styles and offsets - (and c-file-style - (c-set-style c-file-style)) - (and c-file-offsets - (mapcar - (function - (lambda (langentry) - (let ((langelem (car langentry)) - (offset (cdr langentry))) - (c-set-offset langelem offset) - ))) - c-file-offsets))) - -(add-hook 'hack-local-variables-hook 'c-postprocess-file-styles) - - -;; Common routines -(defun c-make-inherited-keymap () - (let ((map (make-sparse-keymap))) - (cond - ;; XEmacs 19 & 20 - ((fboundp 'set-keymap-parents) - (set-keymap-parents map c-mode-base-map)) - ;; Emacs 19 - ((fboundp 'set-keymap-parent) - (set-keymap-parent map c-mode-base-map)) - ;; incompatible - (t (error "CC Mode is incompatible with this version of Emacs"))) - map)) - -(defun c-populate-syntax-table (table) - ;; Populate the syntax TABLE - ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS! - (modify-syntax-entry ?_ "_" table) - (modify-syntax-entry ?\\ "\\" table) - (modify-syntax-entry ?+ "." table) - (modify-syntax-entry ?- "." table) - (modify-syntax-entry ?= "." table) - (modify-syntax-entry ?% "." table) - (modify-syntax-entry ?< "." table) - (modify-syntax-entry ?> "." table) - (modify-syntax-entry ?& "." table) - (modify-syntax-entry ?| "." table) - (modify-syntax-entry ?\' "\"" table) - ;; Set up block and line oriented comments. The new C standard - ;; mandates both comment styles even in C, so since all languages - ;; now require dual comments, we make this the default. - (cond - ;; XEmacs 19 & 20 - ((memq '8-bit c-emacs-features) - (modify-syntax-entry ?/ ". 1456" table) - (modify-syntax-entry ?* ". 23" table)) - ;; Emacs 19 & 20 - ((memq '1-bit c-emacs-features) - (modify-syntax-entry ?/ ". 124b" table) - (modify-syntax-entry ?* ". 23" table)) - ;; incompatible - (t (error "CC Mode is incompatible with this version of Emacs")) - ) - (modify-syntax-entry ?\n "> b" table) - ;; Give CR the same syntax as newline, for selective-display - (modify-syntax-entry ?\^m "> b" table)) - - -(defvar c-mode-base-map () - "Keymap shared by all CC Mode related modes.") - -(if c-mode-base-map - nil - ;; TBD: should we even worry about naming this keymap. My vote: no, - ;; because Emacs and XEmacs do it differently. - (setq c-mode-base-map (make-sparse-keymap)) - ;; put standard keybindings into MAP - ;; the following mappings correspond more or less directly to BOCM - (define-key c-mode-base-map "{" 'c-electric-brace) - (define-key c-mode-base-map "}" 'c-electric-brace) - (define-key c-mode-base-map ";" 'c-electric-semi&comma) - (define-key c-mode-base-map "#" 'c-electric-pound) - (define-key c-mode-base-map ":" 'c-electric-colon) - ;; Lucid Emacs 19.9 defined these two, the second of which was - ;; commented out... - ;; (define-key c-mode-base-map "\e{" 'c-insert-braces) - ;; Commented out electric square brackets because nobody likes them. - ;; (define-key c-mode-base-map "[" 'c-insert-brackets) - (define-key c-mode-base-map "\C-c\C-m" 'c-mark-function) - (define-key c-mode-base-map "\e\C-q" 'c-indent-exp) - (define-key c-mode-base-map "\ea" 'c-beginning-of-statement) - (define-key c-mode-base-map "\ee" 'c-end-of-statement) - (define-key c-mode-base-map "\C-c\C-n" 'c-forward-conditional) - (define-key c-mode-base-map "\C-c\C-p" 'c-backward-conditional) - (define-key c-mode-base-map "\C-c\C-u" 'c-up-conditional) - (define-key c-mode-base-map "\t" 'c-indent-command) - ;; Caution! Enter here at your own risk. We are trying to support - ;; several behaviors and it gets disgusting. :-( - ;; - ;; In XEmacs 19, Emacs 19, and Emacs 20, we use this to bind - ;; backwards deletion behavior to DEL, which both Delete and - ;; Backspace get translated to. There's no way to separate this - ;; behavior in a clean way, so deal with it! Besides, it's been - ;; this way since the dawn of BOCM. - (if (not (boundp 'delete-key-deletes-forward)) - (define-key c-mode-base-map "\177" 'c-electric-backspace) - ;; However, XEmacs 20 actually achieved enlightenment. It is - ;; possible to sanely define both backward and forward deletion - ;; behavior under X separately (TTYs are forever beyond hope, but - ;; who cares? XEmacs 20 does the right thing with these too). - (define-key c-mode-base-map [delete] 'c-electric-delete) - (define-key c-mode-base-map [backspace] 'c-electric-backspace)) - ;; these are new keybindings, with no counterpart to BOCM - (define-key c-mode-base-map "," 'c-electric-semi&comma) - (define-key c-mode-base-map "*" 'c-electric-star) - (define-key c-mode-base-map "/" 'c-electric-slash) - (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) - (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region) - ;; TBD: where if anywhere, to put c-backward|forward-into-nomenclature - (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-state) - (define-key c-mode-base-map "\C-c\C-b" 'c-submit-bug-report) - (define-key c-mode-base-map "\C-c\C-c" 'comment-region) - (define-key c-mode-base-map "\C-c\C-d" 'c-toggle-hungry-state) - (define-key c-mode-base-map "\C-c\C-o" 'c-set-offset) - (define-key c-mode-base-map "\C-c\C-s" 'c-show-syntactic-information) - (define-key c-mode-base-map "\C-c\C-t" 'c-toggle-auto-hungry-state) - (define-key c-mode-base-map "\C-c." 'c-set-style) - ;; conflicts with OOBR - ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) - ) - -;; menu support for both XEmacs and Emacs. If you don't have easymenu -;; with your version of Emacs, you are incompatible! -(require 'easymenu) - -(defvar c-c-menu nil) -(defvar c-c++-menu nil) -(defvar c-objc-menu nil) -(defvar c-java-menu nil) - -(defun c-mode-menu (modestr) - (let ((m - '(["Comment Out Region" comment-region (mark)] - ["Uncomment Region" - (comment-region (region-beginning) (region-end) '(4)) - (mark)] - ["Fill Comment Paragraph" c-fill-paragraph t] - "---" - ["Indent Expression" c-indent-exp - (memq (char-after) '(?\( ?\[ ?\{))] - ["Indent Line" c-indent-command t] - ["Up Conditional" c-up-conditional t] - ["Backward Conditional" c-backward-conditional t] - ["Forward Conditional" c-forward-conditional t] - ["Backward Statement" c-beginning-of-statement t] - ["Forward Statement" c-end-of-statement t] - "---" - ["Macro Expand Region" c-macro-expand (mark)] - ["Backslashify" c-backslash-region (mark)] - ))) - (cons modestr m))) - - - -;; Support for C - -(defvar c-mode-abbrev-table nil - "Abbreviation table used in c-mode buffers.") -(define-abbrev-table 'c-mode-abbrev-table ()) - -(defvar c-mode-map () - "Keymap used in c-mode buffers.") -(if c-mode-map - nil - (setq c-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for C - (define-key c-mode-map "\C-c\C-e" 'c-macro-expand) - ) - -;;;###autoload -(defvar c-mode-syntax-table nil - "Syntax table used in c-mode buffers.") -(if c-mode-syntax-table - () - (setq c-mode-syntax-table (make-syntax-table)) - (c-populate-syntax-table c-mode-syntax-table)) - -(easy-menu-define c-c-menu c-mode-map "C Mode Commands" - (c-mode-menu "C")) - - -;; Support for C++ - -(defvar c++-mode-abbrev-table nil - "Abbreviation table used in c++-mode buffers.") -(define-abbrev-table 'c++-mode-abbrev-table ()) - -(defvar c++-mode-map () - "Keymap used in c++-mode buffers.") -(if c++-mode-map - nil - (setq c++-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for C++ - (define-key c++-mode-map "\C-c\C-e" 'c-macro-expand) - (define-key c++-mode-map "\C-c:" 'c-scope-operator) - (define-key c++-mode-map "<" 'c-electric-lt-gt) - (define-key c++-mode-map ">" 'c-electric-lt-gt)) - -;;;###autoload -(defvar c++-mode-syntax-table nil - "Syntax table used in c++-mode buffers.") -(if c++-mode-syntax-table - () - (setq c++-mode-syntax-table (make-syntax-table)) - (c-populate-syntax-table c++-mode-syntax-table) - ;; TBD: does it make sense for colon to be symbol class in C++? - ;; I'm not so sure, since c-label-key is busted on lines like: - ;; Foo::bar( i ); - ;; maybe c-label-key should be fixed instead of commenting this out, - ;; but it also bothers me that this only seems appropriate for C++ - ;; and not C. - ;;(modify-syntax-entry ?: "_" c++-mode-syntax-table) - ) - -(easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands" - (c-mode-menu "C++")) - - -;; Support for Objective-C - -(defvar objc-mode-abbrev-table nil - "Abbreviation table used in objc-mode buffers.") -(define-abbrev-table 'objc-mode-abbrev-table ()) - -(defvar objc-mode-map () - "Keymap used in objc-mode buffers.") -(if objc-mode-map - nil - (setq objc-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for Objective-C - (define-key objc-mode-map "\C-c\C-e" 'c-macro-expand)) - -;;;###autoload -(defvar objc-mode-syntax-table nil - "Syntax table used in objc-mode buffers.") -(if objc-mode-syntax-table - () - (setq objc-mode-syntax-table (make-syntax-table)) - (c-populate-syntax-table objc-mode-syntax-table) - ;; add extra Objective-C only syntax - (modify-syntax-entry ?@ "_" objc-mode-syntax-table)) - -(easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands" - (c-mode-menu "ObjC")) - - -;; Support for Java - -(defvar java-mode-abbrev-table nil - "Abbreviation table used in java-mode buffers.") -(define-abbrev-table 'java-mode-abbrev-table ()) - -(defvar java-mode-map () - "Keymap used in java-mode buffers.") -(if java-mode-map - nil - (setq java-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for Java - ) - -;;;###autoload -(defvar java-mode-syntax-table nil - "Syntax table used in java-mode buffers.") -(if java-mode-syntax-table - () - (setq java-mode-syntax-table (make-syntax-table)) - (c-populate-syntax-table java-mode-syntax-table)) - -(easy-menu-define c-java-menu java-mode-map "Java Mode Commands" - (c-mode-menu "Java")) - - -;; Support for CORBA's IDL language - -(defvar idl-mode-abbrev-table nil - "Abbreviation table used in idl-mode buffers.") -(define-abbrev-table 'idl-mode-abbrev-table ()) - -(defvar idl-mode-map () - "Keymap used in idl-mode buffers.") -(if idl-mode-map - nil - (setq idl-mode-map (c-make-inherited-keymap)) - ;; add bindings which are only useful for IDL - ) - -;;;###autoload -(defvar idl-mode-syntax-table nil - "Syntax table used in idl-mode buffers.") -(if idl-mode-syntax-table - nil - (setq idl-mode-syntax-table (make-syntax-table)) - (c-populate-syntax-table idl-mode-syntax-table)) - -(easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands" - (c-mode-menu "IDL")) - - - -(provide 'cc-langs) -;;; cc-langs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-menus.el --- a/lisp/cc-mode/cc-menus.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,364 +0,0 @@ -;;; cc-menus.el --- imenu support for CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - -;; imenu integration -(defvar cc-imenu-c-prototype-macro-regexp nil - "RE matching macro names used to conditionally specify function prototypes. - -For example: - - #ifdef __STDC__ - #define _P(x) x - #else - #define _P(x) /*nothing*/ - #endif - - int main _P( (int argc, char *argv[]) ) - -A sample value might look like: `\\(_P\\|_PROTO\\)'.") - -(defvar cc-imenu-c++-generic-expression - (` - ( - ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' - ;; will be incorrectly recognised as function `new ()' because the regexps - ;; work by backtracking from the end of the definition. - (nil - (, - (concat - "^\\<.*" - "[^a-zA-Z0-9_:<>~]" ; match any non-identifier char - ; (note: this can be `\n') - "\\(" - "\\([a-zA-Z0-9_:<>~]*::\\)?" ; match an operator - "operator\\>[ \t]*" - "\\(()\\|[^(]*\\)" ; special case for `()' operator - "\\)" - - "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, - ; require something other than - ; a `;' after the (...) to - ; avoid prototypes. Can't - ; catch cases with () inside - ; the parentheses surrounding - ; the parameters. e.g.: - ; `int foo(int a=bar()) {...}' - )) 1) - ;; Special case to match a line like `main() {}' - ;; e.g. no return type, not even on the previous line. - (nil - (, - (concat - "^" - "\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name - "[ \t]*([^)]*)[ \t]*[^ \t;]" ; see above - )) 1) - ;; General function name regexp - (nil - (, - (concat - "^\\<.*" ; line MUST start with word char - "[^a-zA-Z0-9_:<>~]" ; match any non-identifier char - "\\([a-zA-Z_][a-zA-Z0-9_:<>~]*\\)" ; match function name - "[ \t]*(" ; see above, BUT - "[ \t]*[^ \t(][^)]*)[ \t]*[^ \t;]" ; the argument list must not start - ; with a parentheses - )) 1) - ;; Special case for definitions using phony prototype macros like: - ;; `int main _PROTO( (int argc,char *argv[]) )'. - ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. - ;; Only supported in c-code, so no `:<>~' chars in function name! - (,@ (if cc-imenu-c-prototype-macro-regexp - (` ((nil - (, - (concat - "^\\<.*" ; line MUST start with word char - "[^a-zA-Z0-9_]" ; match any non-identifier char - "\\([a-zA-Z_][a-zA-Z0-9_]*\\)" ; match function name - "[ \t]*" ; whitespace before macro name - cc-imenu-c-prototype-macro-regexp - "[ \t]*(" ; ws followed by first paren. - "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above - )) 1))))) - ;; Class definitions - ("Class" - (, (concat - "^" ; beginning of line is required - "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' - "class[ \t]+" - "\\([a-zA-Z0-9_]+\\)" ; the string we want to get - "[ \t]*[:{]" - )) 2))) - "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") - -(defvar cc-imenu-c-generic-expression - cc-imenu-c++-generic-expression - "Imenu generic expression for C mode. See `imenu-generic-expression'.") - -(defvar cc-imenu-java-generic-expression - (` - ((nil - (, - (concat - "^\\([ \t]\\)*" - "\\([A-Za-z0-9_-]+[ \t]+\\)?" ; type specs; there can be - "\\([A-Za-z0-9_-]+[ \t]+\\)?" ; more than 3 tokens, right? - "\\([A-Za-z0-9_-]+[ \t]*[[]?[]]?\\)" - "\\([ \t]\\)" - "\\([A-Za-z0-9_-]+\\)" ; the string we want to get - "\\([ \t]*\\)+(" - "\\([a-zA-Z,_1-9\n \t]*[[]?[]]?\\)*" ; arguments - ")[ \t]*" -; "[^;(]" - "[,a-zA-Z_1-9\n \t]*{" - )) 6))) - "Imenu generic expression for Java mode. See `imenu-generic-expression'.") - -(defvar cc-imenu-objc-generic-expression - (concat - ;; - ;; For C - ;; *Warning for developers* - ;; This expression elements depend on `cc-imenu-c++-generic-expression'. - ;; - ;; > Special case to match a line like `main() {}' - ;; > e.g. no return type, not even on the previous line. - ;; Pick a token by (match-string 1) - (car (cdr (nth 1 cc-imenu-c++-generic-expression))) ; - "\\|" - ;; > General function name regexp - ;; Pick a token by (match-string 2) - (car (cdr (nth 2 cc-imenu-c++-generic-expression))) - ;; > Special case for definitions using phony prototype macros like: - ;; > `int main _PROTO( (int argc,char *argv[]) )'. - ;; Pick a token by (match-string 3) - (if cc-imenu-c-prototype-macro-regexp - (concat - "\\|" - (car (cdr (nth 3 cc-imenu-c++-generic-expression)))) - "") - ;; - ;; For Objective-C - ;; Pick a token by (match-string 3 or 4) - ;; - "\\|\\(" - "^[-+][:a-zA-Z0-9()*_<>\n\t ]*[;{]" ; Methods - "\\|" - "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*:" - "\\|" - "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)" - "\\|" - ;; For NSObject, NSProxy and Object... They don't have super class. - "^@interface[\t ]+[a-zA-Z0-9_]+[\t ]*.*$" - "\\|" - "^@implementation[\t ]+[a-zA-Z0-9_]+[\t ]*([a-zA-Z0-9_]+)" - "\\|" - "^@implementation[\t ]+[a-zA-Z0-9_]+" - "\\|" - "^@protocol[\t ]+[a-zA-Z0-9_]+" "\\)") - "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") - - -;; Imenu support for objective-c uses functions. -(defsubst cc-imenu-objc-method-to-selector (method) - "Return the objc selector style string of METHOD. -Example: -- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ -=> --perform:withObject:withObject:withObject: /* selector */" - (let ((return "") ; String to be returned - (p 0) ; Current scanning position in METHOD - (pmax (length method)) ; - char ; Current scanning target - (betweenparen 0) ; CHAR is in parentheses. - argreq ; An argument is required. - inargvar) ; position of CHAR is in an argument variable. - (while (< p pmax) - (setq char (aref method p) - p (1+ p)) - (cond - ;; Is CHAR part of a objc token? - ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. - (eq 0 betweenparen) ; Ignore if CHAR is in parentheses. - (or (and (<= ?a char) (<= char ?z)) - (and (<= ?A char) (<= char ?Z)) - (and (<= ?0 char) (<= char ?9)) - (= ?_ char))) - (if argreq - (setq inargvar t - argreq nil) - (setq return (concat return (char-to-string char))))) - ;; Or a white space? - ((and inargvar (or (eq ?\ char) (eq ?\n char)) - (setq inargvar nil))) - ;; Or a method separator? - ;; If a method separator, the next token will be an argument variable. - ((eq ?: char) - (setq argreq t - return (concat return (char-to-string char)))) - ;; Or an open parentheses? - ((eq ?\( char) - (setq betweenparen (1+ betweenparen))) - ;; Or a close parentheses? - ((eq ?\) char) - (setq betweenparen (1- betweenparen))))) - return)) - -(defun cc-imenu-objc-remove-white-space (str) - "Remove all spaces and tabs from STR." - (let ((return "") - (p 0) - (max (length str)) - char) - (while (< p max) - (setq char (aref str p)) - (setq p (1+ p)) - (if (or (= char ?\ ) (= char ?\t)) - () - (setq return (concat return (char-to-string char))))) - return)) - -(defun cc-imenu-objc-function () - "imenu supports for objc-mode." - (let (methodlist - clist - ;; - ;; OBJC, C1, C2, C3 are constants. - ;; - ;; *Warning for developers* - ;; These constants depend on `cc-imenu-c++-generic-expression'. - ;; - (OBJC - (if cc-imenu-c-prototype-macro-regexp 4 3)) - (C1 ; > Special case to match a line like `main() {}' - 1) - (C2 ; > General function name regexp - 2) - (C3 ; > Special case for definitions using phony prototype macros like: - 3) - langnum - ;; - (classcount 0) - toplist - stupid - str - str2 - (intflen (length "@interface")) - (implen (length "@implementation")) - (prtlen (length "@protocol")) - bufsubst-fun) - ;; - ;; Does this emacs has buffer-substring-no-properties? - ;; - (fset 'bufsubst-fun (if (fboundp 'buffer-substring-no-properties) - (symbol-function 'buffer-substring-no-properties) - (symbol-function 'buffer-substring))) - (goto-char (point-max)) - (imenu-progress-message stupid 0) - ;; - (while (re-search-backward cc-imenu-objc-generic-expression nil t) - (imenu-progress-message stupid) - (setq langnum (if (match-beginning OBJC) - OBJC - (cond - ((match-beginning C3) C3) - ((match-beginning C2) C2) - ((match-beginning C1) C1)))) - (setq str (bufsubst-fun (match-beginning langnum) (match-end langnum))) - ;; - (cond - ;; - ;; C - ;; - ((not (eq langnum OBJC)) - (setq clist (cons (cons str (match-beginning langnum)) clist))) - ;; - ;; ObjC - ;; - ;; An instance Method - ((eq (aref str 0) ?-) - (setq str (concat "-" (cc-imenu-objc-method-to-selector str))) - (setq methodlist (cons (cons str - (match-beginning langnum)) - methodlist))) - ;; A factory Method - ((eq (aref str 0) ?+) - (setq str (concat "+" (cc-imenu-objc-method-to-selector str))) - (setq methodlist (cons (cons str - (match-beginning langnum)) - methodlist))) - ;; Interface or implementation or protocol - ((eq (aref str 0) ?@) - (setq classcount (1+ classcount)) - (cond - ((and (> (length str) implen) - (string= (substring str 0 implen) "@implementation")) - (setq str (substring str implen) - str2 "@implementation")) - ((string= (substring str 0 intflen) "@interface") - (setq str (substring str intflen) - str2 "@interface")) - ((string= (substring str 0 prtlen) "@protocol") - (setq str (substring str prtlen) - str2 "@protocol"))) - (setq str (cc-imenu-objc-remove-white-space str)) - (setq methodlist (cons (cons str2 - (match-beginning langnum)) - methodlist)) - (setq toplist (cons nil (cons (cons str - methodlist) toplist)) - methodlist nil)))) - ;; - (imenu-progress-message stupid 100) - (if (eq (car toplist) nil) - (setq toplist (cdr toplist))) - - ;; In this buffer, there is only one or zero @{interface|implementation|protocol}. - (if (< classcount 2) - (let ((classname (car (car toplist))) - (p (cdr (car (cdr (car toplist))))) - last) - (setq toplist (cons (cons classname p) (cdr (cdr (car toplist))))) - ;; Add C lang token - (if clist - (progn - (setq last toplist) - (while (cdr last) - (setq last (cdr last))) - (setcdr last clist)))) - ;; Add C lang tokens as a sub menu - (setq toplist (cons (cons "C" clist) toplist))) - ;; - toplist - )) - - -(provide 'cc-menus) -;;; cc-menus.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-mode.el --- a/lisp/cc-mode/cc-mode.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -;;; cc-mode.el --- major mode for editing C, C++, Objective-C, and Java code - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: a long, long, time ago. adapted from the original c-mode.el -;; Keywords: c languages oop - -(defconst c-version "5.19" - "CC Mode version number.") - -;; NOTE: Read the commentary below for the right way to submit bug reports! -;; NOTE: See the accompanying texinfo manual for details on using this mode! - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: - -;; This package provides GNU Emacs major modes for editing C, C++, -;; Objective-C, Java and IDL code. As of the latest Emacs and XEmacs -;; releases, it is the default package for editing these languages. -;; This package is called "CC Mode", and should be spelled exactly -;; this way. It supports K&R and ANSI C, ANSI C++, Objective-C, Java, -;; and CORBA's IDL with a consistent indentation model across all -;; modes. This indentation model is intuitive and very flexible, so -;; that almost any desired style of indentation can be supported. -;; Installation, usage, and programming details are contained in an -;; accompanying texinfo manual. - -;; CC Mode's immediate ancestors were, c++-mode.el, cplus-md.el, and -;; cplus-md1.el.. - -;; NOTE: This mode does not perform font-locking (a.k.a syntactic -;; coloring, keyword highlighting, etc.) for any of the supported -;; modes. Typically this is done by a package called font-lock.el -;; which I do *not* maintain. You should contact the Emacs -;; maintainers for questions about coloring or highlighting in any -;; language mode. - -;; To submit bug reports, type "C-c C-b". These will be sent to -;; bug-gnu-emacs@prep.ai.mit.edu as well as cc-mode-help@python.org, -;; and I'll read about them there (the former is mirrored as the -;; Usenet newsgroup gnu.emacs.bug). Questions can sent to -;; help-gnu-emacs@prep.ai.mit.edu (mirrored as gnu.emacs.help) and/or -;; cc-mode-help@python.org. Please do not send bugs or questions to -;; my personal account. - -;; Many, many thanks go out to all the folks on the beta test list. -;; Without their patience, testing, insight, code contributions, and -;; encouragement CC Mode would be a far inferior package. - -;; You can get the latest version of CC Mode, including PostScript -;; documentation and separate individual files from: -;; -;; http://www.python.org/ftp/emacs/ - -;; Or if you don't have access to the World Wide Web, through -;; anonymous ftp from: -;; -;; ftp://ftp.python.org/pub/emacs - -;;; Code: - -(eval-when-compile - (require 'cc-menus)) -(require 'cc-defs) - -(defvar c-buffer-is-cc-mode nil - "Non-nil for all buffers with a `major-mode' derived from CC Mode. -Otherwise, this variable is nil. I.e. this variable is non-nil for -`c-mode', `c++-mode', `objc-mode', `java-mode', `idl-mode', and any -other non-CC Mode mode that calls `c-initialize-cc-mode' -\(e.g. `awk-mode').") -(make-variable-buffer-local 'c-buffer-is-cc-mode) -(put 'c-buffer-is-cc-mode 'permanent-local t) - - -;; Other modes and packages which depend on CC Mode should do the -;; following to make sure everything is loaded and available for their -;; use: -;; -;; (require 'cc-mode) -;; (c-initialize-cc-mode) - -;;;###autoload -(defun c-initialize-cc-mode () - (setq c-buffer-is-cc-mode t) - ;; sigh. give in to the pressure, but make really sure all the - ;; definitions we need are here - (if (or (not (fboundp 'functionp)) - (not (fboundp 'char-before)) - (not (c-safe (char-after) t))) - (require 'cc-mode-19)) - ;; make sure all necessary components of CC Mode are loaded in. - (let ((initprop 'cc-mode-is-initialized)) - (require 'cc-vars) - (require 'cc-engine) - (require 'cc-langs) - (require 'cc-menus) - (require 'cc-align) - (require 'cc-styles) - (require 'cc-cmds) - ;; run the initialization hook, but only once - (or (get 'c-initialize-cc-mode initprop) - (progn - (c-initialize-builtin-style) - (run-hooks 'c-initialization-hook) - (put 'c-initialize-cc-mode initprop t))) - )) - - -;;;###autoload -(defun c-mode () - "Major mode for editing K&R and ANSI C code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -c-mode buffer. This automatically sets up a mail buffer with version -information already added. You just need to add a description of the -problem, including a reproducible test case and send the message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `c-mode-hook' is run with no args, if that value is -bound and has a non-nil value. Also the hook `c-mode-common-hook' is -run first. - -Key bindings: -\\{c-mode-map}" - (interactive) - (c-initialize-cc-mode) - (kill-all-local-variables) - (set-syntax-table c-mode-syntax-table) - (setq major-mode 'c-mode - mode-name "C" - local-abbrev-table c-mode-abbrev-table) - (use-local-map c-mode-map) - (c-common-init) - (setq comment-start "/* " - comment-end " */" - c-conditional-key c-C-conditional-key - c-class-key c-C-class-key - c-baseclass-key nil - c-comment-start-regexp c-C++-comment-start-regexp - imenu-generic-expression cc-imenu-c-generic-expression) - (run-hooks 'c-mode-common-hook) - (run-hooks 'c-mode-hook) - (c-update-modeline)) - - -;;;###autoload -(defun c++-mode () - "Major mode for editing C++ code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -c++-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case, and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `c++-mode-hook' is run with no args, if that -variable is bound and has a non-nil value. Also the hook -`c-mode-common-hook' is run first. - -Key bindings: -\\{c++-mode-map}" - (interactive) - (c-initialize-cc-mode) - (kill-all-local-variables) - (set-syntax-table c++-mode-syntax-table) - (setq major-mode 'c++-mode - mode-name "C++" - local-abbrev-table c++-mode-abbrev-table) - (use-local-map c++-mode-map) - (c-common-init) - (setq comment-start "// " - comment-end "" - c-conditional-key c-C++-conditional-key - c-comment-start-regexp c-C++-comment-start-regexp - c-class-key c-C++-class-key - c-access-key c-C++-access-key - c-recognize-knr-p nil - imenu-generic-expression cc-imenu-c++-generic-expression) - (run-hooks 'c-mode-common-hook) - (run-hooks 'c++-mode-hook) - (c-update-modeline)) - - -;;;###autoload -(defun objc-mode () - "Major mode for editing Objective C code. -To submit a problem report, enter `\\[c-submit-bug-report]' from an -objc-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case, and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `objc-mode-hook' is run with no args, if that value -is bound and has a non-nil value. Also the hook `c-mode-common-hook' -is run first. - -Key bindings: -\\{objc-mode-map}" - (interactive) - (c-initialize-cc-mode) - (kill-all-local-variables) - (set-syntax-table objc-mode-syntax-table) - (setq major-mode 'objc-mode - mode-name "ObjC" - local-abbrev-table objc-mode-abbrev-table) - (use-local-map objc-mode-map) - (c-common-init) - (setq comment-start "// " - comment-end "" - c-conditional-key c-C-conditional-key - c-comment-start-regexp c-C++-comment-start-regexp - c-class-key c-ObjC-class-key - c-baseclass-key nil - c-access-key c-ObjC-access-key - c-method-key c-ObjC-method-key - imenu-create-index-function 'cc-imenu-objc-function) - (run-hooks 'c-mode-common-hook) - (run-hooks 'objc-mode-hook) - (c-update-modeline)) - - -;;;###autoload -(defun java-mode () - "Major mode for editing Java code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -java-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `java-mode-hook' is run with no args, if that value -is bound and has a non-nil value. Also the common hook -`c-mode-common-hook' is run first. Note that this mode automatically -sets the \"java\" style before calling any hooks so be careful if you -set styles in `c-mode-common-hook'. - -Key bindings: -\\{java-mode-map}" - (interactive) - (c-initialize-cc-mode) - (kill-all-local-variables) - (set-syntax-table java-mode-syntax-table) - (setq major-mode 'java-mode - mode-name "Java" - local-abbrev-table java-mode-abbrev-table) - (use-local-map java-mode-map) - (c-common-init) - (setq comment-start "// " - comment-end "" - c-conditional-key c-Java-conditional-key - c-comment-start-regexp c-Java-comment-start-regexp - c-class-key c-Java-class-key - c-method-key c-Java-method-key - c-baseclass-key nil - c-recognize-knr-p nil - c-access-key c-Java-access-key - ;defun-prompt-regexp c-Java-defun-prompt-regexp - imenu-generic-expression cc-imenu-java-generic-expression - ) - (c-set-style "java") - (run-hooks 'c-mode-common-hook) - (run-hooks 'java-mode-hook) - (c-update-modeline)) - - -;;;###autoload -(defun idl-mode () - "Major mode for editing CORBA's IDL code. -To submit a problem report, enter `\\[c-submit-bug-report]' from a -idl-mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case, and send the -message. - -To see what version of CC Mode you are running, enter `\\[c-version]'. - -The hook variable `idl-mode-hook' is run with no args, if that -variable is bound and has a non-nil value. Also the hook -`c-mode-common-hook' is run first. - -Key bindings: -\\{idl-mode-map}" - (interactive) - (c-initialize-cc-mode) - (kill-all-local-variables) - (set-syntax-table idl-mode-syntax-table) - (setq major-mode 'idl-mode - mode-name "IDL" - local-abbrev-table idl-mode-abbrev-table) - (use-local-map idl-mode-map) - (c-common-init) - (setq comment-start "// " - comment-end "" - c-conditional-key c-C++-conditional-key - c-comment-start-regexp c-C++-comment-start-regexp - c-class-key c-C++-class-key - c-access-key c-C++-access-key - c-recognize-knr-p nil) -;; imenu-generic-expression cc-imenu-c++-generic-expression) - (run-hooks 'c-mode-common-hook) - (run-hooks 'idl-mode-hook) - (c-update-modeline)) - - -;; bug reporting - -(defconst c-mode-help-address - "bug-gnu-emacs@prep.ai.mit.edu, cc-mode-help@python.org" - "Address for CC Mode bug reports.") - -(defun c-version () - "Echo the current version of CC Mode in the minibuffer." - (interactive) - (message "Using CC Mode version %s" c-version) - (c-keep-region-active)) - -;; Get reporter-submit-bug-report when byte-compiling -(eval-when-compile - (require 'reporter)) - -(defun c-submit-bug-report () - "Submit via mail a bug report on CC Mode." - (interactive) - (require 'cc-vars) - ;; load in reporter - (let ((reporter-prompt-for-summary-p t) - (reporter-dont-compact-list '(c-offsets-alist)) - (style c-indentation-style) - (hook c-special-indent-hook) - (c-features c-emacs-features)) - (and - (if (y-or-n-p "Do you want to submit a report on CC Mode? ") - t (message "") nil) - (require 'reporter) - (reporter-submit-bug-report - c-mode-help-address - (concat "CC Mode " c-version " (" - (cond ((eq major-mode 'c++-mode) "C++") - ((eq major-mode 'c-mode) "C") - ((eq major-mode 'objc-mode) "ObjC") - ((eq major-mode 'java-mode) "Java") - ) - ")") - (let ((vars (list - ;; report only the vars that affect indentation - 'c-basic-offset - 'c-offsets-alist - 'c-cleanup-list - 'c-comment-only-line-offset - 'c-backslash-column - 'c-delete-function - 'c-electric-pound-behavior - 'c-hanging-braces-alist - 'c-hanging-colons-alist - 'c-hanging-comment-starter-p - 'c-hanging-comment-ender-p - 'c-indent-comments-syntactically-p - 'c-tab-always-indent - 'c-comment-continuation-stars - 'c-label-minimum-indentation - 'defun-prompt-regexp - 'tab-width - ))) - (if (not (boundp 'defun-prompt-regexp)) - (delq 'defun-prompt-regexp vars) - vars)) - (function - (lambda () - (insert - "Buffer Style: " style "\n\n" - (if hook - (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" - "c-special-indent-hook is set to '" - (format "%s" hook) - ".\nPerhaps this is your problem?\n" - "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n") - "\n") - (format "c-emacs-features: %s\n" c-features) - ))) - nil - "Dear Barry," - )))) - - -(provide 'cc-mode) -;;; cc-mode.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-styles.el --- a/lisp/cc-mode/cc-styles.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,645 +0,0 @@ -;;; cc-styles.el --- support for styles in CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - - - -(defconst c-style-alist - '(("gnu" - (c-basic-offset . 2) - (c-comment-only-line-offset . (0 . 0)) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . 5) - (substatement-open . +) - (label . 0) - (statement-case-open . +) - (statement-cont . +) - (arglist-intro . c-lineup-arglist-intro-after-paren) - (arglist-close . c-lineup-arglist) - )) - (c-special-indent-hook . c-gnu-impose-minimum) - (c-comment-continuation-stars . "") - (c-hanging-comment-ender-p . t) - ) - ("k&r" - (c-basic-offset . 5) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . 0) - (substatement-open . 0) - (label . 0) - (statement-cont . +) - )) - ) - ("bsd" - (c-basic-offset . 4) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . +) - (substatement-open . 0) - (label . 0) - (statement-cont . +) - )) - ) - ("stroustrup" - (c-basic-offset . 4) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (substatement-open . 0) - (label . 0) - (statement-cont . +) - )) - ) - ("whitesmith" - (c-basic-offset . 4) - (c-comment-only-line-offset . 0) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . +) - (substatement-open . 0) - (label . 0) - (statement-cont . +) - )) - - ) - ("ellemtel" - (c-basic-offset . 3) - (c-comment-only-line-offset . 0) - (c-hanging-braces-alist . ((substatement-open before after))) - (c-offsets-alist . ((topmost-intro . 0) - (topmost-intro-cont . 0) - (substatement . +) - (substatement-open . 0) - (case-label . +) - (access-label . -) - (inclass . ++) - (inline-open . 0) - )) - ) - ("linux" - (c-basic-offset . 8) - (c-comment-only-line-offset . 0) - (c-hanging-braces-alist . ((brace-list-open) - (substatement-open after) - (block-close . c-snug-do-while))) - (c-cleanup-list . (brace-else-brace)) - (c-offsets-alist . ((statement-block-intro . +) - (knr-argdecl-intro . 0) - (substatement-open . 0) - (label . 0) - (statement-cont . +) - )) - ) - ("python" - (indent-tabs-mode . t) - (fill-column . 72) - (c-basic-offset . 8) - (c-offsets-alist . ((substatement-open . 0) - (inextern-lang . 0) - (arglist-intro . +) - (knr-argdecl-intro . +) - )) - (c-hanging-braces-alist . ((brace-list-open) - (brace-list-intro) - (brace-list-close) - (substatement-open after) - (block-close . c-snug-do-while) - )) - (c-comment-continuation-stars . "") - (c-hanging-comment-ender-p . nil) - (fill-column . 78) - ) - ("java" - (c-basic-offset . 2) - (c-comment-only-line-offset . (0 . 0)) - ;; the following preserves Javadoc starter lines - (c-hanging-comment-starter-p . nil) - (c-offsets-alist . ((topmost-intro-cont . +) - (statement-block-intro . +) - (knr-argdecl-intro . 5) - (substatement-open . +) - (label . 0) - (statement-case-open . +) - (statement-cont . +) - (arglist-intro . c-lineup-arglist-intro-after-paren) - (arglist-close . c-lineup-arglist) - (access-label . 0) - (inher-cont . c-lineup-java-inher) - (func-decl-cont . c-lineup-java-throws) - )) - - ) - ) - "Styles of indentation. -Elements of this alist are of the form: - - (STYLE-STRING [BASE-STYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) - -where STYLE-STRING is a short descriptive string used to select a -style, VARIABLE is any Emacs variable, and VALUE is the intended value -for that variable when using the selected style. - -Optional BASE-STYLE if present, is a string and must follow -STYLE-STRING. BASE-STYLE names a style that this style inherits from. -By default, all styles inherit from the \"cc-mode\" style, which is -computed at run time. Style loops generate errors. - -Two variables are treated specially. When VARIABLE is -`c-offsets-alist', the VALUE is a list containing elements of the -form: - - (SYNTACTIC-SYMBOL . OFFSET) - -as described in `c-offsets-alist'. These are passed directly to -`c-set-offset' so there is no need to set every syntactic symbol in -your style, only those that are different from the default. - -When VARIABLE is `c-special-indent-hook', its VALUE is added to -`c-special-indent-hook' using `add-hook'. If VALUE is a list, each -element of the list is added with `add-hook'. - -Do not change this variable directly. Use the function `c-add-style' -to add new styles or modify existing styles (it is not a good idea to -modify existing styles -- you should create a new style that inherits -the existing style.") - - -;; Functions that manipulate styles -(defun c-set-style-1 (conscell) - ;; Set the style for one variable - (let ((attr (car conscell)) - (val (cdr conscell))) - (cond - ;; first special variable - ((eq attr 'c-offsets-alist) - (mapcar - (function - (lambda (langentry) - (let ((langelem (car langentry)) - (offset (cdr langentry))) - (c-set-offset langelem offset) - ))) - val)) - ;; second special variable - ((eq attr 'c-special-indent-hook) - (if (listp val) - (while val - (add-hook 'c-special-indent-hook (car val)) - (setq val (cdr val))) - (add-hook 'c-special-indent-hook val))) - ;; all other variables - (t (set attr val))) - )) - -(defun c-set-style-2 (style basestyles) - ;; Recursively set the base style. If no base style is given, the - ;; default base style is "cc-mode" and the recursion stops. Be sure - ;; to detect loops. - (let ((vars (cdr (or (assoc (downcase style) c-style-alist) - (assoc (upcase style) c-style-alist) - (assoc style c-style-alist) - (error "Undefined style: %s" style))))) - (if (not (string-equal style "cc-mode")) - (let ((base (if (stringp (car vars)) - (prog1 - (downcase (car vars)) - (setq vars (cdr vars))) - "cc-mode"))) - (if (memq base basestyles) - (error "Style loop detected: %s in %s" base basestyles)) - (c-set-style-2 base (cons base basestyles)))) - (mapcar 'c-set-style-1 vars))) - -(defvar c-set-style-history nil) - -;;;###autoload -(defun c-set-style (stylename) - "Set CC Mode variables to use one of several different indentation styles. -STYLENAME is a string representing the desired style from the list of -styles described in the variable `c-style-alist'. See that variable -for details of setting up styles. - -The variable `c-indentation-style' always contains the buffer's current -style name." - (interactive (list (let ((completion-ignore-case t) - (prompt (format "Which %s indentation style? " - mode-name))) - (completing-read prompt c-style-alist nil t - (cons c-indentation-style 0) - 'c-set-style-history)))) - (c-initialize-builtin-style) - (c-set-style-2 stylename nil) - (setq c-indentation-style stylename) - (c-keep-region-active)) - -;;;###autoload -(defun c-add-style (style descrip &optional set-p) - "Adds a style to `c-style-alist', or updates an existing one. -STYLE is a string identifying the style to add or update. DESCRIP is -an association list describing the style and must be of the form: - - ([BASESTYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) - -See the variable `c-style-alist' for the semantics of BASESTYLE, -VARIABLE and VALUE. This function also sets the current style to -STYLE using `c-set-style' if the optional SET-P flag is non-nil." - (interactive - (let ((stylename (completing-read "Style to add: " c-style-alist - nil nil nil 'c-set-style-history)) - (description (eval-minibuffer "Style description: "))) - (list stylename description - (y-or-n-p "Set the style too? ")))) - (setq style (downcase style)) - (let ((s (assoc style c-style-alist))) - (if s - (setcdr s (copy-alist descrip)) ; replace - (setq c-style-alist (cons (cons style descrip) c-style-alist)))) - (and set-p (c-set-style style))) - - - -(defconst c-offsets-alist - '((string . -1000) - (c . c-lineup-C-comments) - (defun-open . 0) - (defun-close . 0) - (defun-block-intro . +) - (class-open . 0) - (class-close . 0) - (inline-open . +) - (inline-close . 0) - (func-decl-cont . +) - (knr-argdecl-intro . +) - (knr-argdecl . 0) - (topmost-intro . 0) - (topmost-intro-cont . 0) - (member-init-intro . +) - (member-init-cont . 0) - (inher-intro . +) - (inher-cont . c-lineup-multi-inher) - (block-open . 0) - (block-close . 0) - (brace-list-open . 0) - (brace-list-close . 0) - (brace-list-intro . +) - (brace-list-entry . 0) - (statement . 0) - ;; some people might prefer - ;;(statement . c-lineup-runin-statements) - (statement-cont . +) - ;; some people might prefer - ;;(statement-cont . c-lineup-math) - (statement-block-intro . +) - (statement-case-intro . +) - (statement-case-open . 0) - (substatement . +) - (substatement-open . +) - (case-label . 0) - (access-label . -) - (label . 2) - (do-while-closure . 0) - (else-clause . 0) - (comment-intro . c-lineup-comment) - (arglist-intro . +) - (arglist-cont . 0) - (arglist-cont-nonempty . c-lineup-arglist) - (arglist-close . +) - (stream-op . c-lineup-streamop) - (inclass . +) - (cpp-macro . -1000) - (friend . 0) - (objc-method-intro . -1000) - (objc-method-args-cont . c-lineup-ObjC-method-args) - (objc-method-call-cont . c-lineup-ObjC-method-call) - (extern-lang-open . 0) - (extern-lang-close . 0) - (inextern-lang . +) - (template-args-cont . +) - ) - "Association list of syntactic element symbols and indentation offsets. -As described below, each cons cell in this list has the form: - - (SYNTACTIC-SYMBOL . OFFSET) - -When a line is indented, CC Mode first determines the syntactic -context of the line by generating a list of symbols called syntactic -elements. This list can contain more than one syntactic element and -the global variable `c-syntactic-context' contains the context list -for the line being indented. Each element in this list is actually a -cons cell of the syntactic symbol and a buffer position. This buffer -position is called the relative indent point for the line. Some -syntactic symbols may not have a relative indent point associated with -them. - -After the syntactic context list for a line is generated, CC Mode -calculates the absolute indentation for the line by looking at each -syntactic element in the list. First, it compares the syntactic -element against the SYNTACTIC-SYMBOL's in `c-offsets-alist'. When it -finds a match, it adds the OFFSET to the column of the relative indent -point. The sum of this calculation for each element in the syntactic -list is the absolute offset for line being indented. - -If the syntactic element does not match any in the `c-offsets-alist', -an error is generated if `c-strict-syntax-p' is non-nil, otherwise the -element is ignored. - -Actually, OFFSET can be an integer, a function, a variable, or one of -the following symbols: `+', `-', `++', `--', `*', or `/'. These -latter designate positive or negative multiples of `c-basic-offset', -respectively: 1, -1, 2, -2, 0.5, and -0.5. If OFFSET is a function, it -is called with a single argument containing the cons of the syntactic -element symbol and the relative indent point. The function should -return an integer offset. - -Here is the current list of valid syntactic element symbols: - - string -- inside multi-line string - c -- inside a multi-line C style block comment - defun-open -- brace that opens a function definition - defun-close -- brace that closes a function definition - defun-block-intro -- the first line in a top-level defun - class-open -- brace that opens a class definition - class-close -- brace that closes a class definition - inline-open -- brace that opens an in-class inline method - inline-close -- brace that closes an in-class inline method - func-decl-cont -- the region between a function definition's - argument list and the function opening brace - (excluding K&R argument declarations). In C, you - cannot put anything but whitespace and comments - between them; in C++ and Java, throws declarations - and other things can appear in this context. - knr-argdecl-intro -- first line of a K&R C argument declaration - knr-argdecl -- subsequent lines in a K&R C argument declaration - topmost-intro -- the first line in a topmost construct definition - topmost-intro-cont -- topmost definition continuation lines - member-init-intro -- first line in a member initialization list - member-init-cont -- subsequent member initialization list lines - inher-intro -- first line of a multiple inheritance list - inher-cont -- subsequent multiple inheritance lines - block-open -- statement block open brace - block-close -- statement block close brace - brace-list-open -- open brace of an enum or static array list - brace-list-close -- close brace of an enum or static array list - brace-list-intro -- first line in an enum or static array list - brace-list-entry -- subsequent lines in an enum or static array list - statement -- a C (or like) statement - statement-cont -- a continuation of a C (or like) statement - statement-block-intro -- the first line in a new statement block - statement-case-intro -- the first line in a case \"block\" - statement-case-open -- the first line in a case block starting with brace - substatement -- the first line after an if/while/for/do/else - substatement-open -- the brace that opens a substatement block - case-label -- a `case' or `default' label - access-label -- C++ private/protected/public access label - label -- any ordinary label - do-while-closure -- the `while' that ends a do/while construct - else-clause -- the `else' of an if/else construct - comment-intro -- a line containing only a comment introduction - arglist-intro -- the first line in an argument list - arglist-cont -- subsequent argument list lines when no - arguments follow on the same line as the - arglist opening paren - arglist-cont-nonempty -- subsequent argument list lines when at - least one argument follows on the same - line as the arglist opening paren - arglist-close -- the solo close paren of an argument list - stream-op -- lines continuing a stream operator construct - inclass -- the construct is nested inside a class definition - cpp-macro -- the start of a cpp macro - friend -- a C++ friend declaration - objc-method-intro -- the first line of an Objective-C method definition - objc-method-args-cont -- lines continuing an Objective-C method definition - objc-method-call-cont -- lines continuing an Objective-C method call - extern-lang-open -- brace that opens an external language block - extern-lang-close -- brace that closes an external language block - inextern-lang -- analogous to `inclass' syntactic symbol - template-args-cont -- C++ template argument list continuations -") - -(defun c-get-offset (langelem) - ;; Get offset from LANGELEM which is a cons cell of the form: - ;; (SYMBOL . RELPOS). The symbol is matched against - ;; c-offsets-alist and the offset found there is either returned, - ;; or added to the indentation at RELPOS. If RELPOS is nil, then - ;; the offset is simply returned. - (let* ((symbol (car langelem)) - (relpos (cdr langelem)) - (match (assq symbol c-offsets-alist)) - (offset (cdr-safe match))) - ;; offset can be a number, a function, a variable, or one of the - ;; symbols + or - - (cond - ((not match) - (if c-strict-syntax-p - (error "don't know how to indent a %s" symbol) - (setq offset 0 - relpos 0))) - ((eq offset '+) (setq offset c-basic-offset)) - ((eq offset '-) (setq offset (- c-basic-offset))) - ((eq offset '++) (setq offset (* 2 c-basic-offset))) - ((eq offset '--) (setq offset (* 2 (- c-basic-offset)))) - ((eq offset '*) (setq offset (/ c-basic-offset 2))) - ((eq offset '/) (setq offset (/ (- c-basic-offset) 2))) - ((functionp offset) (setq offset (funcall offset langelem))) - ((not (numberp offset)) (setq offset (symbol-value offset))) - ) - (+ (if (and relpos - (< relpos (c-point 'bol))) - (save-excursion - (goto-char relpos) - (current-column)) - 0) - offset))) - - -(defvar c-read-offset-history nil) - -(defun c-read-offset (langelem) - ;; read new offset value for LANGELEM from minibuffer. return a - ;; legal value only - (let* ((oldoff (cdr-safe (assq langelem c-offsets-alist))) - (defstr (format "(default %s): " oldoff)) - (errmsg (concat "Offset must be int, func, var, " - "or in [+,-,++,--,*,/] " - defstr)) - (prompt (concat "Offset " defstr)) - offset input interned raw) - (while (not offset) - (setq input (completing-read prompt obarray 'fboundp nil nil - 'c-read-offset-history) - offset (cond ((string-equal "" input) oldoff) ; default - ((string-equal "+" input) '+) - ((string-equal "-" input) '-) - ((string-equal "++" input) '++) - ((string-equal "--" input) '--) - ((string-equal "*" input) '*) - ((string-equal "/" input) '/) - ((string-match "^-?[0-9]+$" input) - (string-to-int input)) - ;; a symbol with a function binding - ((fboundp (setq interned (intern input))) - interned) - ;; a lambda function - ((c-safe (functionp (setq raw (read input)))) - raw) - ;; a symbol with variable binding - ((boundp interned) interned) - ;; error, but don't signal one, keep trying - ;; to read an input value - (t (ding) - (setq prompt errmsg) - nil)))) - offset)) - -;;;###autoload -(defun c-set-offset (symbol offset &optional add-p) - "Change the value of a syntactic element symbol in `c-offsets-alist'. -SYMBOL is the syntactic element symbol to change and OFFSET is the new -offset for that syntactic element. Optional ADD says to add SYMBOL to -`c-offsets-alist' if it doesn't already appear there." - (interactive - (let* ((langelem - (intern (completing-read - (concat "Syntactic symbol to change" - (if current-prefix-arg " or add" "") - ": ") - (mapcar - #'(lambda (langelem) - (cons (format "%s" (car langelem)) nil)) - c-offsets-alist) - nil (not current-prefix-arg) - ;; initial contents tries to be the last element - ;; on the syntactic analysis list for the current - ;; line - (let* ((syntax (c-guess-basic-syntax)) - (len (length syntax)) - (ic (format "%s" (car (nth (1- len) syntax))))) - (cons ic 0)) - ))) - (offset (c-read-offset langelem))) - (list langelem offset current-prefix-arg))) - ;; sanity check offset - (or (eq offset '+) - (eq offset '-) - (eq offset '++) - (eq offset '--) - (eq offset '*) - (eq offset '/) - (integerp offset) - (functionp offset) - (boundp offset) - (error "Offset must be int, func, var, or in [+,-,++,--,*,/]: %s" - offset)) - (let ((entry (assq symbol c-offsets-alist))) - (if entry - (setcdr entry offset) - (if add-p - (setq c-offsets-alist (cons (cons symbol offset) c-offsets-alist)) - (error "%s is not a valid syntactic symbol." symbol)))) - (c-keep-region-active)) - - - -(defun c-initialize-builtin-style () - ;; Dynamically append the default value of most variables. This is - ;; crucial because future c-set-style calls will always reset the - ;; variables first to the `cc-mode' style before instituting the new - ;; style. Only do this once! - (or (assoc "cc-mode" c-style-alist) - (let (copyfunc) - ;; use built-in copy-tree if its there. - (if (and (fboundp 'copy-tree) - (functionp (symbol-function 'copy-tree))) - (setq copyfunc (symbol-function 'copy-tree)) - (setq copyfunc (lambda (tree) - (if (consp tree) - (cons (funcall copyfunc (car tree)) - (funcall copyfunc (cdr tree))) - tree)))) - (c-add-style "cc-mode" - (mapcar - (function - (lambda (var) - (let ((val (symbol-value var))) - (cons var (if (atom val) - val - (funcall copyfunc val) - )) - ))) - '(c-backslash-column - c-basic-offset - c-cleanup-list - c-comment-only-line-offset - c-electric-pound-behavior - c-hanging-braces-alist - c-hanging-colons-alist - c-hanging-comment-starter-p - c-hanging-comment-ender-p - c-offsets-alist - ))) - ;; the default style is now GNU. This can be overridden in - ;; c-mode-common-hook or {c,c++,objc,java}-mode-hook. - (c-set-style c-site-default-style))) - (if c-style-variables-are-local-p - (c-make-styles-buffer-local))) - - -(defun c-make-styles-buffer-local () - "Make all CC Mode style variables buffer local. -If you edit primarily one style of C (or C++, Objective-C, Java) code, -you probably want style variables to be global. This is the default. - -If you edit many different styles of C (or C++, Objective-C, Java) at -the same time, you probably want the CC Mode style variables to be -buffer local. If you do, then you will need to set any CC Mode style -variables in a hook function (e.g. off of c-mode-common-hook), instead -of at the top level of your ~/.emacs file. - -This function makes all the CC Mode style variables buffer local. -Call it after CC Mode is loaded into your Emacs environment. -Conversely, set the variable `c-style-variables-are-local-p' to t in -your .emacs file, before CC Mode is loaded, and this function will be -automatically called when CC Mode is loaded." - ;; style variables - (make-variable-buffer-local 'c-offsets-alist) - (make-variable-buffer-local 'c-basic-offset) - (make-variable-buffer-local 'c-file-style) - (make-variable-buffer-local 'c-file-offsets) - (make-variable-buffer-local 'c-comment-only-line-offset) - (make-variable-buffer-local 'c-cleanup-list) - (make-variable-buffer-local 'c-hanging-braces-alist) - (make-variable-buffer-local 'c-hanging-colons-alist) - (make-variable-buffer-local 'c-hanging-comment-starter-p) - (make-variable-buffer-local 'c-hanging-comment-ender-p) - (make-variable-buffer-local 'c-backslash-column) - (make-variable-buffer-local 'c-label-minimum-indentation) - (make-variable-buffer-local 'c-special-indent-hook) - (make-variable-buffer-local 'c-indentation-style)) - - -(provide 'cc-styles) -;;; cc-styles.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/cc-vars.el --- a/lisp/cc-mode/cc-vars.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,415 +0,0 @@ -;;; cc-vars.el --- user customization variables for CC Mode - -;; Copyright (C) 1985,87,92,93,94,95,96,97 Free Software Foundation, Inc. - -;; Authors: 1992-1997 Barry A. Warsaw -;; 1987 Dave Detlefs and Stewart Clamen -;; 1985 Richard M. Stallman -;; Maintainer: cc-mode-help@python.org -;; Created: 22-Apr-1997 (split from cc-mode.el) -;; Version: See cc-mode.el -;; Keywords: c languages oop - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -(require 'custom) - - -(defcustom c-strict-syntax-p nil - "*If non-nil, all syntactic symbols must be found in `c-offsets-alist'. -If the syntactic symbol for a particular line does not match a symbol -in the offsets alist, an error is generated, otherwise no error is -reported and the syntactic symbol is ignored." - :type 'boolean - :group 'c) - -(defcustom c-echo-syntactic-information-p nil - "*If non-nil, syntactic info is echoed when the line is indented." - :type 'boolean - :group 'c) - -(defcustom c-basic-offset 4 - "*Amount of basic offset used by + and - symbols in `c-offsets-alist'." - :type 'integer - :group 'c) - -(defcustom c-tab-always-indent t - "*Controls the operation of the TAB key. -If t, hitting TAB always just indents the current line. If nil, -hitting TAB indents the current line if point is at the left margin or -in the line's indentation, otherwise it insert a `real' tab character -\(see note\). If other than nil or t, then tab is inserted only -within literals -- defined as comments and strings -- and inside -preprocessor directives, but line is always reindented. - -Note: The value of `indent-tabs-mode' will determine whether a real -tab character will be inserted, or the equivalent number of space. -When inserting a tab, actually the function stored in the variable -`c-insert-tab-function' is called. - -Note: indentation of lines containing only comments is also controlled -by the `c-comment-only-line-offset' variable." - :type '(radio - :extra-offset 8 - :format "%{C Tab Always Indent%}:\n The TAB key:\n%v" - (const :tag "always indents, never inserts TAB" t) - (const :tag "indents in left margin, otherwise inserts TAB" nil) - (const :tag "inserts TAB in literals, otherwise indent" other)) - :group 'c) - -(defcustom c-insert-tab-function 'insert-tab - "*Function used when inserting a tab for \\[TAB]. -Only used when `c-tab-always-indent' indicates a `real' tab character -should be inserted. Value must be a function taking no arguments." - :type 'function - :group 'c) - -(defcustom c-comment-only-line-offset 0 - "*Extra offset for line which contains only the start of a comment. -Can contain an integer or a cons cell of the form: - - (NON-ANCHORED-OFFSET . ANCHORED-OFFSET) - -Where NON-ANCHORED-OFFSET is the amount of offset given to -non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is -the amount of offset to give column-zero anchored comment-only lines. -Just an integer as value is equivalent to ( . -1000)." - :type '(choice (integer :tag "Non-anchored offset") - (cons :tag "Non-anchored & anchored offset" - :value (0 . 0) - :extra-offset 8 - (integer :tag "Non-anchored offset") - (integer :tag "Anchored offset"))) - :group 'c) - -(defcustom c-indent-comments-syntactically-p nil - "*Specifies how comment-only lines should be indented. -When this variable is non-nil, comment-only lines are indented -according to syntactic analysis via `c-offsets-alist', even when -\\[indent-for-comment] is used." - :type 'boolean - :group 'c) - -(defcustom c-comment-continuation-stars "* " - "*Specifies the leader of continued block comments. -You should set this variable to the literal string that gets inserted -at the front of continued block style comment lines. This should -either be the empty string, or some number of stars followed by a -single space. Note that for line style comments, this variable is not -used." - :type '(choice (const :tag "Use old semantics" nil) - string) - :group 'c) - -(defcustom c-cleanup-list '(scope-operator) - "*List of various C/C++/ObjC constructs to \"clean up\". -These clean ups only take place when the auto-newline feature is -turned on, as evidenced by the `/a' or `/ah' appearing next to the -mode name. Valid symbols are: - - brace-else-brace -- cleans up `} else {' constructs by placing entire - construct on a single line. This clean up - only takes place when there is nothing but - white space between the braces and the `else'. - Clean up occurs when the open-brace after the - `else' is typed. - brace-elseif-brace -- similar to brace-else-brace, but cleans up - `} else if {' constructs. - empty-defun-braces -- cleans up empty defun braces by placing the - braces on the same line. Clean up occurs when - the defun closing brace is typed. - defun-close-semi -- cleans up the terminating semi-colon on defuns - by placing the semi-colon on the same line as - the closing brace. Clean up occurs when the - semi-colon is typed. - list-close-comma -- cleans up commas following braces in array - and aggregate initializers. Clean up occurs - when the comma is typed. - scope-operator -- cleans up double colons which may designate - a C++ scope operator split across multiple - lines. Note that certain C++ constructs can - generate ambiguous situations. This clean up - only takes place when there is nothing but - whitespace between colons. Clean up occurs - when the second colon is typed." - :type '(set - :extra-offset 8 - (const :tag "Put `} else {' on one line" brace-else-brace) - (const :tag "Put `} else if {' on one line" brace-elseif-brace) - (const :tag "Put empty defun braces on one line" empty-defun-braces) - (const :tag "Put `},' in aggregates on one line" list-close-comma) - (const :tag "Put C++ style `::' on one line" scope-operator)) - :group 'c) - -(defcustom c-hanging-braces-alist '((brace-list-open) - (substatement-open after) - (block-close . c-snug-do-while) - (extern-lang-open after) - ) - "*Controls the insertion of newlines before and after braces. -This variable contains an association list with elements of the -following form: (SYNTACTIC-SYMBOL . ACTION). - -When a brace (either opening or closing) is inserted, the syntactic -context it defines is looked up in this list, and if found, the -associated ACTION is used to determine where newlines are inserted. -If the context is not found, the default is to insert a newline both -before and after the brace. - -SYNTACTIC-SYMBOL can be any of: defun-open, defun-close, class-open, -class-close, inline-open, inline-close, block-open, block-close, -substatement-open, statement-case-open, extern-lang-open, -extern-lang-close, brace-list-open, brace-list-close, -brace-list-intro, or brace-list-entry. See `c-offsets-alist' for -details. - -ACTION can be either a function symbol or a list containing any -combination of the symbols `before' or `after'. If the list is empty, -no newlines are inserted either before or after the brace. - -When ACTION is a function symbol, the function is called with a two -arguments: the syntactic symbol for the brace and the buffer position -at which the brace was inserted. The function must return a list as -described in the preceding paragraph. Note that during the call to -the function, the variable `c-syntactic-context' is set to the entire -syntactic context for the brace line." - :type '(repeat - (cons :format "%v" - (choice :tag "Syntax" - (const defun-open) (const defun-close) - (const class-open) (const class-close) - (const inline-open) (const inline-close) - (const block-open) (const block-close) - (const substatement-open) (const statement-case-open) - (const extern-lang-open) (const extern-lang-close) - (const brace-list-open) (const brace-list-close) - (const brace-list-intro) (const brace-list-entry)) - (choice :tag "Action" - (set :format "Insert a newline %v" - :extra-offset 38 - (const :tag "before brace" before) - (const :tag "after brace" after)) - (function :format "Run function %v" :value c-) - ))) - :group 'c) - -(defcustom c-hanging-colons-alist nil - "*Controls the insertion of newlines before and after certain colons. -This variable contains an association list with elements of the -following form: (SYNTACTIC-SYMBOL . ACTION). - -SYNTACTIC-SYMBOL can be any of: case-label, label, access-label, -member-init-intro, or inher-intro. - -See the variable `c-hanging-braces-alist' for the semantics of this -variable. Note however that making ACTION a function symbol is -currently not supported for this variable." - :type '(repeat - (cons :format "%v" - (choice :tag "Syntax" - (const case-label) (const label) (const access-label) - (const member-init-intro) (const inher-intro)) - (set :tag "Action" - :format "%t: %v" - :extra-offset 8 - (const before) (const after)))) - :group 'c) - -(defcustom c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist) - "*List of functions that decide whether to insert a newline or not. -The functions in this list are called, in order, whenever the -auto-newline minor mode is activated (as evidenced by a `/a' or `/ah' -string in the mode line), and a semicolon or comma is typed (see -`c-electric-semi&comma'). Each function in this list is called with -no arguments, and should return one of the following values: - - nil -- no determination made, continue checking - 'stop -- do not insert a newline, and stop checking - (anything else) -- insert a newline, and stop checking - -If every function in the list is called with no determination made, -then no newline is inserted." - :type '(repeat function) - :group 'c) - -(defcustom c-hanging-comment-ender-p t - "*Controls what \\[fill-paragraph] does to C block comment enders. -When set to nil, C block comment enders are left on their own line. -When set to t, block comment enders will be placed at the end of the -previous line (i.e. they `hang' on that line)." - :type 'boolean - :group 'c) - -(defcustom c-hanging-comment-starter-p t - "*Controls what \\[fill-paragraph] does to C block comment starters. -When set to nil, C block comment starters are left on their own line. -When set to t, text that follows a block comment starter will be -placed on the same line as the block comment starter (i.e. the text -`hangs' on that line)." - :type 'boolean - :group 'c) - -(defcustom c-backslash-column 48 - "*Column to insert backslashes when macroizing a region." - :type 'integer - :group 'c) - -(defcustom c-special-indent-hook nil - "*Hook for user defined special indentation adjustments. -This hook gets called after a line is indented by the mode." - :type 'hook - :group 'c) - -(defcustom c-backspace-function 'backward-delete-char-untabify - "*Function called by `c-electric-backspace' when deleting backwards." - :type 'function - :group 'c) - -(defcustom c-delete-function 'delete-char - "*Function called by `c-electric-delete' when deleting forwards." - :type 'function - :group 'c) - -(defcustom c-electric-pound-behavior nil - "*List of behaviors for electric pound insertion. -Only currently supported behavior is `alignleft'." - :type '(set :extra-offset 8 (const alignleft)) - :group 'c) - -(defcustom c-label-minimum-indentation 1 - "*Minimum indentation for lines inside of top-level constructs. -This variable typically only affects code using the `gnu' style, which -mandates a minimum of one space in front of every line inside -top-level constructs. Specifically, the function -`c-gnu-impose-minimum' on your `c-special-indent-hook' is what -enforces this." - :type 'integer - :group 'c) - -(defcustom c-progress-interval 5 - "*Interval used to update progress status during long re-indentation. -If a number, percentage complete gets updated after each interval of -that many seconds. To inhibit all messages during indentation, set -this variable to nil." - :type 'integer - :group 'c) - -(defcustom c-site-default-style "gnu" - "Default style for your site. -To change the default style at your site, you can set this variable to -any style defined in `c-style-alist'. However, if CC Mode is usually -loaded into your Emacs at compile time, you will need to set this -variable in the `site-init.el' file before CC Mode is loaded, then -re-dump Emacs." - :type 'string - :group 'c) - -(defcustom c-style-variables-are-local-p nil - "*Whether style variables should be buffer local by default. -If non-nil, then all indentation style related variables will be made -buffer local by default. If nil, they will remain global. Variables -are made buffer local when this file is loaded, and once buffer -localized, they cannot be made global again. - -The list of variables to buffer localize are: - c-offsets-alist - c-basic-offset - c-file-style - c-file-offsets - c-comment-only-line-offset - c-cleanup-list - c-hanging-braces-alist - c-hanging-colons-alist - c-hanging-comment-starter-p - c-hanging-comment-ender-p - c-backslash-column - c-label-minimum-indentation - c-special-indent-hook - c-indentation-style" - :type 'boolean - :group 'c) - -(defcustom c-mode-hook nil - "*Hook called by `c-mode'." - :type '(hook :format "%{C Mode Hook%}:\n%v") - :group 'c) - -(defcustom c++-mode-hook nil - "*Hook called by `c++-mode'." - :type 'hook - :group 'c) - -(defcustom objc-mode-hook nil - "*Hook called by `objc-mode'." - :type 'hook - :group 'c) - -(defcustom java-mode-hook nil - "*Hook called by `java-mode'." - :type 'hook - :group 'c) - -(defcustom idl-mode-hook nil - "*Hook called by `idl-mode'." - :type 'hook - :group 'c) - -(defcustom c-mode-common-hook nil - "*Hook called by all CC Mode modes for common initializations." - :type '(hook :format "%{CC Mode Common Hook%}:\n%v") - :group 'c) - -(defcustom c-initialization-hook nil - "*Hook called when the CC Mode package gets initialized. -This hook is only run once per Emacs session and can be used as a -`load-hook' or in place of using `eval-after-load'." - :type 'hook - :group 'c) - - - -;; Non-customizable variables, still part of the interface to CC Mode -(defvar c-file-style nil - "Variable interface for setting style via File Local Variables. -In a file's Local Variable section, you can set this variable to a -string suitable for `c-set-style'. When the file is visited, CC Mode -will set the style of the file to this value automatically. - -Note that file style settings are applied before file offset settings -as designated in the variable `c-file-offsets'.") - -(defvar c-file-offsets nil - "Variable interface for setting offsets via File Local Variables. -In a file's Local Variable section, you can set this variable to an -association list similar to the values allowed in `c-offsets-alist'. -When the file is visited, CC Mode will institute these offset settings -automatically. - -Note that file offset settings are applied after file style settings -as designated in the variable `c-file-style'.") - -(defvar c-syntactic-context nil - "Variable containing syntactic analysis list during indentation.") - -(defvar c-indentation-style c-site-default-style - "Name of style installed in the current buffer.") - - - -(provide 'cc-vars) -;;; cc-vars.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cc-mode/custom-load.el --- a/lisp/cc-mode/custom-load.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -;;; custom-load.el --- automatically extracted custom dependencies - - -;;; Code: - -(custom-add-loads 'c '("cc-vars")) - -;;; custom-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl-compat.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cl-compat.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,194 @@ +;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility) + +;; Copyright (C) 1993 Free Software Foundation, Inc. + +;; Author: Dave Gillespie +;; Version: 2.02 +;; Keywords: extensions + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; These are extensions to Emacs Lisp that provide a degree of +;; Common Lisp compatibility, beyond what is already built-in +;; in Emacs Lisp. +;; +;; This package was written by Dave Gillespie; it is a complete +;; rewrite of Cesar Quiroz's original cl.el package of December 1986. +;; +;; This package works with Emacs 18, Emacs 19, and XEmacs/Lucid Emacs 19. +;; +;; Bug reports, comments, and suggestions are welcome! + +;; This file contains emulations of internal routines of the older +;; CL package which users may have called directly from their code. +;; Use (require 'cl-compat) to get these routines. + +;; See cl.el for Change Log. + + +;;; Code: + +;; Require at load-time, but not when compiling cl-compat. +(or (featurep 'cl) (require 'cl)) + + +;;; Keyword routines not supported by new package. + +(defmacro defkeyword (x &optional doc) + (list* 'defconst x (list 'quote x) (and doc (list doc)))) + +(defun keywordp (sym) + (and (symbolp sym) (eq (aref (symbol-name sym) 0) ?\:) (set sym sym))) + +(defun keyword-of (sym) + (or (keywordp sym) (keywordp (intern (format ":%s" sym))))) + + +;;; Multiple values. Note that the new package uses a different +;;; convention for multiple values. The following definitions +;;; emulate the old convention; all function names have been changed +;;; by capitalizing the first letter: Values, Multiple-value-*, +;;; to avoid conflict with the new-style definitions in cl-macs. + +(put 'Multiple-value-bind 'lisp-indent-function 2) +(put 'Multiple-value-setq 'lisp-indent-function 2) +(put 'Multiple-value-call 'lisp-indent-function 1) +(put 'Multiple-value-prog1 'lisp-indent-function 1) + +(defvar *mvalues-values* nil) + +(defun Values (&rest val-forms) + (setq *mvalues-values* val-forms) + (car val-forms)) + +(defun Values-list (val-forms) + (apply 'values val-forms)) + +(defmacro Multiple-value-list (form) + (list 'let* (list '(*mvalues-values* nil) (list '*mvalues-temp* form)) + '(or (and (eq *mvalues-temp* (car *mvalues-values*)) *mvalues-values*) + (list *mvalues-temp*)))) + +(defmacro Multiple-value-call (function &rest args) + (list 'apply function + (cons 'append + (mapcar (function (lambda (x) (list 'Multiple-value-list x))) + args)))) + +(defmacro Multiple-value-bind (vars form &rest body) + (list* 'multiple-value-bind vars (list 'Multiple-value-list form) body)) + +(defmacro Multiple-value-setq (vars form) + (list 'multiple-value-setq vars (list 'Multiple-value-list form))) + +(defmacro Multiple-value-prog1 (form &rest body) + (list 'prog1 form (list* 'let '((*mvalues-values* nil)) body))) + + +;;; Routines for parsing keyword arguments. + +(defun build-klist (arglist keys &optional allow-others) + (let ((res (Multiple-value-call 'mapcar* 'cons (unzip-lists arglist)))) + (or allow-others + (let ((bad (set-difference (mapcar 'car res) keys))) + (if bad (error "Bad keywords: %s not in %s" bad keys)))) + res)) + +(defun extract-from-klist (klist key &optional def) + (let ((res (assq key klist))) (if res (cdr res) def))) + +(defun keyword-argument-supplied-p (klist key) + (assq key klist)) + +(defun elt-satisfies-test-p (item elt klist) + (let ((test-not (cdr (assq ':test-not klist))) + (test (cdr (assq ':test klist))) + (key (cdr (assq ':key klist)))) + (if key (setq elt (funcall key elt))) + (if test-not (not (funcall test-not item elt)) + (funcall (or test 'eql) item elt)))) + + +;;; Rounding functions with old-style multiple value returns. + +(defun cl-floor (a &optional b) (Values-list (floor* a b))) +(defun cl-ceiling (a &optional b) (Values-list (ceiling* a b))) +(defun cl-round (a &optional b) (Values-list (round* a b))) +(defun cl-truncate (a &optional b) (Values-list (truncate* a b))) + +(defun safe-idiv (a b) + (let* ((q (/ (abs a) (abs b))) + (s (* (signum a) (signum b)))) + (Values q (- a (* s q b)) s))) + + +;; Internal routines. + +(defun pair-with-newsyms (oldforms) + (let ((newsyms (mapcar (function (lambda (x) (gensym))) oldforms))) + (Values (mapcar* 'list newsyms oldforms) newsyms))) + +(defun zip-lists (evens odds) + (mapcan 'list evens odds)) + +(defun unzip-lists (list) + (let ((e nil) (o nil)) + (while list + (setq e (cons (car list) e) o (cons (cadr list) o) list (cddr list))) + (Values (nreverse e) (nreverse o)))) + +(defun reassemble-argslists (list) + (let ((n (apply 'min (mapcar 'length list))) (res nil)) + (while (>= (setq n (1- n)) 0) + (setq res (cons (mapcar (function (lambda (x) (elt x n))) list) res))) + res)) + +(defun duplicate-symbols-p (list) + (let ((res nil)) + (while list + (if (memq (car list) (cdr list)) (setq res (cons (car list) res))) + (setq list (cdr list))) + res)) + + +;;; Setf internals. + +(defun setnth (n list x) + (setcar (nthcdr n list) x)) + +(defun setnthcdr (n list x) + (setcdr (nthcdr (1- n) list) x)) + +(defun setelt (seq n x) + (if (consp seq) (setcar (nthcdr n seq) x) (aset seq n x))) + + +;;; Functions omitted: case-clausify, check-do-stepforms, check-do-endforms, +;;; extract-do-inits, extract-do[*]-steps, select-stepping-forms, +;;; elt-satisfies-if[-not]-p, with-keyword-args, mv-bind-clausify, +;;; all names with embedded `$'. + + +(provide 'cl-compat) + +;;; cl-compat.el ends here + diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl-extra.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cl-extra.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,939 @@ +;;; cl-extra.el --- Common Lisp extensions for GNU Emacs Lisp (part two) + +;; Copyright (C) 1993 Free Software Foundation, Inc. + +;; Author: Dave Gillespie +;; Maintainer: XEmacs Development Team +;; Version: 2.02 +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; These are extensions to Emacs Lisp that provide a degree of +;; Common Lisp compatibility, beyond what is already built-in +;; in Emacs Lisp. +;; +;; This package was written by Dave Gillespie; it is a complete +;; rewrite of Cesar Quiroz's original cl.el package of December 1986. +;; +;; This package works with Emacs 18, Emacs 19, and XEmacs/Lucid Emacs 19. +;; +;; Bug reports, comments, and suggestions are welcome! + +;; This file contains portions of the Common Lisp extensions +;; package which are autoloaded since they are relatively obscure. + +;; See cl.el for Change Log. + + +;;; Code: + +(or (memq 'cl-19 features) + (error "Tried to load `cl-extra' before `cl'!")) + + +;;; We define these here so that this file can compile without having +;;; loaded the cl.el file already. + +(defmacro cl-push (x place) (list 'setq place (list 'cons x place))) +(defmacro cl-pop (place) + (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) + +(defvar cl-emacs-type) + + +;;; Type coercion. + +(defun coerce (x type) + "Coerce OBJECT to type TYPE. +TYPE is a Common Lisp type specifier." + (cond ((eq type 'list) (if (listp x) x (append x nil))) + ((eq type 'vector) (if (vectorp x) x (vconcat x))) + ((eq type 'string) (if (stringp x) x (concat x))) + ((eq type 'array) (if (arrayp x) x (vconcat x))) + ((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0)) + ((and (eq type 'character) (symbolp x)) (coerce (symbol-name x) type)) + ((eq type 'float) (float x)) + ((typep x type) x) + (t (error "Can't coerce %s to type %s" x type)))) + + +;;; Predicates. + +(defun equalp (x y) + "T if two Lisp objects have similar structures and contents. +This is like `equal', except that it accepts numerically equal +numbers of different types (float vs. integer), and also compares +strings case-insensitively." + (cond ((eq x y) t) + ((stringp x) + (and (stringp y) (= (length x) (length y)) + (or (string-equal x y) + (string-equal (downcase x) (downcase y))))) ; lazy but simple! + ((numberp x) + (and (numberp y) (= x y))) + ((consp x) + ;; XEmacs change + (while (and (consp x) (consp y) (equalp (cl-pop x) (cl-pop y)))) + (and (not (consp x)) (equalp x y))) + ((vectorp x) + (and (vectorp y) (= (length x) (length y)) + (let ((i (length x))) + (while (and (>= (setq i (1- i)) 0) + (equalp (aref x i) (aref y i)))) + (< i 0)))) + (t (equal x y)))) + + +;;; Control structures. + +(defun cl-mapcar-many (cl-func cl-seqs) + (if (cdr (cdr cl-seqs)) + (let* ((cl-res nil) + (cl-n (apply 'min (mapcar 'length cl-seqs))) + (cl-i 0) + (cl-args (copy-sequence cl-seqs)) + cl-p1 cl-p2) + (setq cl-seqs (copy-sequence cl-seqs)) + (while (< cl-i cl-n) + (setq cl-p1 cl-seqs cl-p2 cl-args) + (while cl-p1 + (setcar cl-p2 + (if (consp (car cl-p1)) + (prog1 (car (car cl-p1)) + (setcar cl-p1 (cdr (car cl-p1)))) + (aref (car cl-p1) cl-i))) + (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2))) + (cl-push (apply cl-func cl-args) cl-res) + (setq cl-i (1+ cl-i))) + (nreverse cl-res)) + (let ((cl-res nil) + (cl-x (car cl-seqs)) + (cl-y (nth 1 cl-seqs))) + (let ((cl-n (min (length cl-x) (length cl-y))) + (cl-i -1)) + (while (< (setq cl-i (1+ cl-i)) cl-n) + (cl-push (funcall cl-func + (if (consp cl-x) (cl-pop cl-x) (aref cl-x cl-i)) + (if (consp cl-y) (cl-pop cl-y) (aref cl-y cl-i))) + cl-res))) + (nreverse cl-res)))) + +(defun map (cl-type cl-func cl-seq &rest cl-rest) + "Map a function across one or more sequences, returning a sequence. +TYPE is the sequence type to return, FUNC is the function, and SEQS +are the argument sequences." + (let ((cl-res (apply 'mapcar* cl-func cl-seq cl-rest))) + (and cl-type (coerce cl-res cl-type)))) + +(defun maplist (cl-func cl-list &rest cl-rest) + "Map FUNC to each sublist of LIST or LISTS. +Like `mapcar', except applies to lists and their cdr's rather than to +the elements themselves." + (if cl-rest + (let ((cl-res nil) + (cl-args (cons cl-list (copy-sequence cl-rest))) + cl-p) + (while (not (memq nil cl-args)) + (cl-push (apply cl-func cl-args) cl-res) + (setq cl-p cl-args) + (while cl-p (setcar cl-p (cdr (cl-pop cl-p)) ))) + (nreverse cl-res)) + (let ((cl-res nil)) + (while cl-list + (cl-push (funcall cl-func cl-list) cl-res) + (setq cl-list (cdr cl-list))) + (nreverse cl-res)))) + + +;; mapc is now in C, renamed from `mapc-internal'. + +;(defun mapc (cl-func cl-seq &rest cl-rest) +; "Like `mapcar', but does not accumulate values returned by the function." +; (if cl-rest +; (apply 'map nil cl-func cl-seq cl-rest) +; ;; XEmacs change: we call mapc-internal, which really doesn't +; ;; accumulate any results. +; (mapc-internal cl-func cl-seq)) +; cl-seq) + +(defun mapl (cl-func cl-list &rest cl-rest) + "Like `maplist', but does not accumulate values returned by the function." + (if cl-rest + (apply 'maplist cl-func cl-list cl-rest) + (let ((cl-p cl-list)) + (while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p))))) + cl-list) + +(defun mapcan (cl-func cl-seq &rest cl-rest) + "Like `mapcar', but nconc's together the values returned by the function." + (apply 'nconc (apply 'mapcar* cl-func cl-seq cl-rest))) + +(defun mapcon (cl-func cl-list &rest cl-rest) + "Like `maplist', but nconc's together the values returned by the function." + (apply 'nconc (apply 'maplist cl-func cl-list cl-rest))) + +(defun some (cl-pred cl-seq &rest cl-rest) + "Return true if PREDICATE is true of any element of SEQ or SEQs. +If so, return the true (non-nil) value returned by PREDICATE." + (if (or cl-rest (nlistp cl-seq)) + (catch 'cl-some + (apply 'map nil + (function (lambda (&rest cl-x) + (let ((cl-res (apply cl-pred cl-x))) + (if cl-res (throw 'cl-some cl-res))))) + cl-seq cl-rest) nil) + (let ((cl-x nil)) + (while (and cl-seq (not (setq cl-x (funcall cl-pred (cl-pop cl-seq)))))) + cl-x))) + +(defun every (cl-pred cl-seq &rest cl-rest) + "Return true if PREDICATE is true of every element of SEQ or SEQs." + (if (or cl-rest (nlistp cl-seq)) + (catch 'cl-every + (apply 'map nil + (function (lambda (&rest cl-x) + (or (apply cl-pred cl-x) (throw 'cl-every nil)))) + cl-seq cl-rest) t) + (while (and cl-seq (funcall cl-pred (car cl-seq))) + (setq cl-seq (cdr cl-seq))) + (null cl-seq))) + +(defun notany (cl-pred cl-seq &rest cl-rest) + "Return true if PREDICATE is false of every element of SEQ or SEQs." + (not (apply 'some cl-pred cl-seq cl-rest))) + +(defun notevery (cl-pred cl-seq &rest cl-rest) + "Return true if PREDICATE is false of some element of SEQ or SEQs." + (not (apply 'every cl-pred cl-seq cl-rest))) + +;;; Support for `loop'. +(defun cl-map-keymap (cl-func cl-map) + (while (symbolp cl-map) (setq cl-map (symbol-function cl-map))) + (if (eq cl-emacs-type 'lucid) (funcall 'map-keymap cl-func cl-map) + (if (listp cl-map) + (let ((cl-p cl-map)) + (while (consp (setq cl-p (cdr cl-p))) + (cond ((consp (car cl-p)) + (funcall cl-func (car (car cl-p)) (cdr (car cl-p)))) + ((vectorp (car cl-p)) + (cl-map-keymap cl-func (car cl-p))) + ((eq (car cl-p) 'keymap) + (setq cl-p nil))))) + (let ((cl-i -1)) + (while (< (setq cl-i (1+ cl-i)) (length cl-map)) + (if (aref cl-map cl-i) + (funcall cl-func cl-i (aref cl-map cl-i)))))))) + +(defun cl-map-keymap-recursively (cl-func-rec cl-map &optional cl-base) + (or cl-base + (setq cl-base (copy-sequence (if (eq cl-emacs-type 18) "0" [0])))) + (cl-map-keymap + (function + (lambda (cl-key cl-bind) + (aset cl-base (1- (length cl-base)) cl-key) + (if (keymapp cl-bind) + (cl-map-keymap-recursively + cl-func-rec cl-bind + (funcall (if (eq cl-emacs-type 18) 'concat 'vconcat) + cl-base (list 0))) + (funcall cl-func-rec cl-base cl-bind)))) + cl-map)) + +(defun cl-map-intervals (cl-func &optional cl-what cl-prop cl-start cl-end) + (or cl-what (setq cl-what (current-buffer))) + (if (bufferp cl-what) + (let (cl-mark cl-mark2 (cl-next t) cl-next2) + (save-excursion + (set-buffer cl-what) + (setq cl-mark (copy-marker (or cl-start (point-min)))) + (setq cl-mark2 (and cl-end (copy-marker cl-end)))) + (while (and cl-next (or (not cl-mark2) (< cl-mark cl-mark2))) + (setq cl-next (and (fboundp 'next-property-change) + (if cl-prop (next-single-property-change + cl-mark cl-prop cl-what) + (next-property-change cl-mark cl-what))) + cl-next2 (or cl-next (save-excursion + (set-buffer cl-what) (point-max)))) + (funcall cl-func (prog1 (marker-position cl-mark) + (set-marker cl-mark cl-next2)) + (if cl-mark2 (min cl-next2 cl-mark2) cl-next2))) + (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil))) + (or cl-start (setq cl-start 0)) + (or cl-end (setq cl-end (length cl-what))) + (while (< cl-start cl-end) + (let ((cl-next (or (and (fboundp 'next-property-change) + (if cl-prop (next-single-property-change + cl-start cl-prop cl-what) + (next-property-change cl-start cl-what))) + cl-end))) + (funcall cl-func cl-start (min cl-next cl-end)) + (setq cl-start cl-next))))) + +(defun cl-map-overlays (cl-func &optional cl-buffer cl-start cl-end cl-arg) + (or cl-buffer (setq cl-buffer (current-buffer))) + (if (fboundp 'overlay-lists) + + ;; This is the preferred algorithm, though overlay-lists is undocumented. + (let (cl-ovl) + (save-excursion + (set-buffer cl-buffer) + (setq cl-ovl (overlay-lists)) + (if cl-start (setq cl-start (copy-marker cl-start))) + (if cl-end (setq cl-end (copy-marker cl-end)))) + (setq cl-ovl (nconc (car cl-ovl) (cdr cl-ovl))) + (while (and cl-ovl + (or (not (overlay-start (car cl-ovl))) + (and cl-end (>= (overlay-start (car cl-ovl)) cl-end)) + (and cl-start (<= (overlay-end (car cl-ovl)) cl-start)) + (not (funcall cl-func (car cl-ovl) cl-arg)))) + (setq cl-ovl (cdr cl-ovl))) + (if cl-start (set-marker cl-start nil)) + (if cl-end (set-marker cl-end nil))) + + ;; This alternate algorithm fails to find zero-length overlays. + (let ((cl-mark (save-excursion (set-buffer cl-buffer) + (copy-marker (or cl-start (point-min))))) + (cl-mark2 (and cl-end (save-excursion (set-buffer cl-buffer) + (copy-marker cl-end)))) + cl-pos cl-ovl) + (while (save-excursion + (and (setq cl-pos (marker-position cl-mark)) + (< cl-pos (or cl-mark2 (point-max))) + (progn + (set-buffer cl-buffer) + (setq cl-ovl (overlays-at cl-pos)) + (set-marker cl-mark (next-overlay-change cl-pos))))) + (while (and cl-ovl + (or (/= (overlay-start (car cl-ovl)) cl-pos) + (not (and (funcall cl-func (car cl-ovl) cl-arg) + (set-marker cl-mark nil))))) + (setq cl-ovl (cdr cl-ovl)))) + (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil))))) + +;;; Support for `setf'. +(defun cl-set-frame-visible-p (frame val) + (cond ((null val) (make-frame-invisible frame)) + ((eq val 'icon) (iconify-frame frame)) + (t (make-frame-visible frame))) + val) + +;;; Support for `progv'. +(defvar cl-progv-save) +(defun cl-progv-before (syms values) + (while syms + (cl-push (if (boundp (car syms)) + (cons (car syms) (symbol-value (car syms))) + (car syms)) cl-progv-save) + (if values + (set (cl-pop syms) (cl-pop values)) + (makunbound (cl-pop syms))))) + +(defun cl-progv-after () + (while cl-progv-save + (if (consp (car cl-progv-save)) + (set (car (car cl-progv-save)) (cdr (car cl-progv-save))) + (makunbound (car cl-progv-save))) + (cl-pop cl-progv-save))) + + +;;; Numbers. + +(defun gcd (&rest args) + "Return the greatest common divisor of the arguments." + (let ((a (abs (or (cl-pop args) 0)))) + (while args + (let ((b (abs (cl-pop args)))) + (while (> b 0) (setq b (% a (setq a b)))))) + a)) + +(defun lcm (&rest args) + "Return the least common multiple of the arguments." + (if (memq 0 args) + 0 + (let ((a (abs (or (cl-pop args) 1)))) + (while args + (let ((b (abs (cl-pop args)))) + (setq a (* (/ a (gcd a b)) b)))) + a))) + +(defun isqrt (a) + "Return the integer square root of the argument." + (if (and (integerp a) (> a 0)) + ;; XEmacs change + (let ((g (cond ((>= a 1000000) 10000) ((>= a 10000) 1000) + ((>= a 100) 100) (t 10))) + g2) + (while (< (setq g2 (/ (+ g (/ a g)) 2)) g) + (setq g g2)) + g) + (if (eq a 0) 0 (signal 'arith-error nil)))) + +(defun cl-expt (x y) + "Return X raised to the power of Y. Works only for integer arguments." + (if (<= y 0) (if (= y 0) 1 (if (memq x '(-1 1)) (cl-expt x (- y)) 0)) + (* (if (= (% y 2) 0) 1 x) (cl-expt (* x x) (/ y 2))))) +(or (and (fboundp 'expt) (subrp (symbol-function 'expt))) + (defalias 'expt 'cl-expt)) + +(defun floor* (x &optional y) + "Return a list of the floor of X and the fractional part of X. +With two arguments, return floor and remainder of their quotient." + (let ((q (floor x y))) + (list q (- x (if y (* y q) q))))) + +(defun ceiling* (x &optional y) + "Return a list of the ceiling of X and the fractional part of X. +With two arguments, return ceiling and remainder of their quotient." + (let ((res (floor* x y))) + (if (= (car (cdr res)) 0) res + (list (1+ (car res)) (- (car (cdr res)) (or y 1)))))) + +(defun truncate* (x &optional y) + "Return a list of the integer part of X and the fractional part of X. +With two arguments, return truncation and remainder of their quotient." + (if (eq (>= x 0) (or (null y) (>= y 0))) + (floor* x y) (ceiling* x y))) + +(defun round* (x &optional y) + "Return a list of X rounded to the nearest integer and the remainder. +With two arguments, return rounding and remainder of their quotient." + (if y + (if (and (integerp x) (integerp y)) + (let* ((hy (/ y 2)) + (res (floor* (+ x hy) y))) + (if (and (= (car (cdr res)) 0) + (= (+ hy hy) y) + (/= (% (car res) 2) 0)) + (list (1- (car res)) hy) + (list (car res) (- (car (cdr res)) hy)))) + (let ((q (round (/ x y)))) + (list q (- x (* q y))))) + (if (integerp x) (list x 0) + (let ((q (round x))) + (list q (- x q)))))) + +(defun mod* (x y) + "The remainder of X divided by Y, with the same sign as Y." + (nth 1 (floor* x y))) + +(defun rem* (x y) + "The remainder of X divided by Y, with the same sign as X." + (nth 1 (truncate* x y))) + +(defun signum (a) + "Return 1 if A is positive, -1 if negative, 0 if zero." + (cond ((> a 0) 1) ((< a 0) -1) (t 0))) + + +;; Random numbers. + +(defvar *random-state*) +(defun random* (lim &optional state) + "Return a random nonnegative number less than LIM, an integer or float. +Optional second arg STATE is a random-state object." + (or state (setq state *random-state*)) + ;; Inspired by "ran3" from Numerical Recipes. Additive congruential method. + (let ((vec (aref state 3))) + (if (integerp vec) + (let ((i 0) (j (- 1357335 (% (abs vec) 1357333))) (k 1) ii) + (aset state 3 (setq vec (make-vector 55 nil))) + (aset vec 0 j) + (while (> (setq i (% (+ i 21) 55)) 0) + (aset vec i (setq j (prog1 k (setq k (- j k)))))) + (while (< (setq i (1+ i)) 200) (random* 2 state)))) + (let* ((i (aset state 1 (% (1+ (aref state 1)) 55))) + (j (aset state 2 (% (1+ (aref state 2)) 55))) + (n (logand 8388607 (aset vec i (- (aref vec i) (aref vec j)))))) + (if (integerp lim) + (if (<= lim 512) (% n lim) + (if (> lim 8388607) (setq n (+ (lsh n 9) (random* 512 state)))) + (let ((mask 1023)) + (while (< mask (1- lim)) (setq mask (1+ (+ mask mask)))) + (if (< (setq n (logand n mask)) lim) n (random* lim state)))) + (* (/ n '8388608e0) lim))))) + +(defun make-random-state (&optional state) + "Return a copy of random-state STATE, or of `*random-state*' if omitted. +If STATE is t, return a new state object seeded from the time of day." + (cond ((null state) (make-random-state *random-state*)) + ((vectorp state) (cl-copy-tree state t)) + ((integerp state) (vector 'cl-random-state-tag -1 30 state)) + (t (make-random-state (cl-random-time))))) + +(defun random-state-p (object) + "Return t if OBJECT is a random-state object." + (and (vectorp object) (= (length object) 4) + (eq (aref object 0) 'cl-random-state-tag))) + + +;; Implementation limits. + +(defun cl-finite-do (func a b) + (condition-case err + (let ((res (funcall func a b))) ; check for IEEE infinity + (and (numberp res) (/= res (/ res 2)) res)) + (arith-error nil))) + +(defvar most-positive-float) +(defvar most-negative-float) +(defvar least-positive-float) +(defvar least-negative-float) +(defvar least-positive-normalized-float) +(defvar least-negative-normalized-float) +(defvar float-epsilon) +(defvar float-negative-epsilon) + +(defun cl-float-limits () + (or most-positive-float (not (numberp '2e1)) + (let ((x '2e0) y z) + ;; Find maximum exponent (first two loops are optimizations) + (while (cl-finite-do '* x x) (setq x (* x x))) + (while (cl-finite-do '* x (/ x 2)) (setq x (* x (/ x 2)))) + (while (cl-finite-do '+ x x) (setq x (+ x x))) + (setq z x y (/ x 2)) + ;; Now fill in 1's in the mantissa. + (while (and (cl-finite-do '+ x y) (/= (+ x y) x)) + (setq x (+ x y) y (/ y 2))) + (setq most-positive-float x + most-negative-float (- x)) + ;; Divide down until mantissa starts rounding. + (setq x (/ x z) y (/ 16 z) x (* x y)) + (while (condition-case err (and (= x (* (/ x 2) 2)) (> (/ y 2) 0)) + (arith-error nil)) + (setq x (/ x 2) y (/ y 2))) + (setq least-positive-normalized-float y + least-negative-normalized-float (- y)) + ;; Divide down until value underflows to zero. + (setq x (/ 1 z) y x) + (while (condition-case err (> (/ x 2) 0) (arith-error nil)) + (setq x (/ x 2))) + (setq least-positive-float x + least-negative-float (- x)) + (setq x '1e0) + (while (/= (+ '1e0 x) '1e0) (setq x (/ x 2))) + (setq float-epsilon (* x 2)) + (setq x '1e0) + (while (/= (- '1e0 x) '1e0) (setq x (/ x 2))) + (setq float-negative-epsilon (* x 2)))) + nil) + + +;;; Sequence functions. + +;XEmacs -- our built-in is more powerful. +;(defun subseq (seq start &optional end) +; "Return the subsequence of SEQ from START to END. +;If END is omitted, it defaults to the length of the sequence. +;If START or END is negative, it counts from the end." +; (if (stringp seq) (substring seq start end) +; (let (len) +; (and end (< end 0) (setq end (+ end (setq len (length seq))))) +; (if (< start 0) (setq start (+ start (or len (setq len (length seq)))))) +; (cond ((listp seq) +; (if (> start 0) (setq seq (nthcdr start seq))) +; (if end +; (let ((res nil)) +; (while (>= (setq end (1- end)) start) +; (cl-push (cl-pop seq) res)) +; (nreverse res)) +; (copy-sequence seq))) +; (t +; (or end (setq end (or len (length seq)))) +; (let ((res (make-vector (max (- end start) 0) nil)) +; (i 0)) +; (while (< start end) +; (aset res i (aref seq start)) +; (setq i (1+ i) start (1+ start))) +; res)))))) + +(defun concatenate (type &rest seqs) + "Concatenate, into a sequence of type TYPE, the argument SEQUENCES." + (cond ((eq type 'vector) (apply 'vconcat seqs)) + ((eq type 'string) (apply 'concat seqs)) + ((eq type 'list) (apply 'append (append seqs '(nil)))) + (t (error "Not a sequence type name: %s" type)))) + + +;;; List functions. + +(defun revappend (x y) + "Equivalent to (append (reverse X) Y)." + (nconc (reverse x) y)) + +(defun nreconc (x y) + "Equivalent to (nconc (nreverse X) Y)." + (nconc (nreverse x) y)) + +(defun list-length (x) + "Return the length of a list. Return nil if list is circular." + (let ((n 0) (fast x) (slow x)) + (while (and (cdr fast) (not (and (eq fast slow) (> n 0)))) + (setq n (+ n 2) fast (cdr (cdr fast)) slow (cdr slow))) + (if fast (if (cdr fast) nil (1+ n)) n))) + +(defun tailp (sublist list) + "Return true if SUBLIST is a tail of LIST." + (while (and (consp list) (not (eq sublist list))) + (setq list (cdr list))) + (if (numberp sublist) (equal sublist list) (eq sublist list))) + +(defun cl-copy-tree (tree &optional vecp) + "Make a copy of TREE. +If TREE is a cons cell, this recursively copies both its car and its cdr. +Contrast to copy-sequence, which copies only along the cdrs. With second +argument VECP, this copies vectors as well as conses." + (if (consp tree) + (let ((p (setq tree (copy-list tree)))) + (while (consp p) + (if (or (consp (car p)) (and vecp (vectorp (car p)))) + (setcar p (cl-copy-tree (car p) vecp))) + (or (listp (cdr p)) (setcdr p (cl-copy-tree (cdr p) vecp))) + (cl-pop p))) + (if (and vecp (vectorp tree)) + (let ((i (length (setq tree (copy-sequence tree))))) + (while (>= (setq i (1- i)) 0) + (aset tree i (cl-copy-tree (aref tree i) vecp)))))) + tree) +(or (and (fboundp 'copy-tree) (subrp (symbol-function 'copy-tree))) + (defalias 'copy-tree 'cl-copy-tree)) + + +;;; Property lists. + +(defun get* (sym tag &optional def) ; See compiler macro in cl-macs.el + "Return the value of SYMBOL's PROPNAME property, or DEFAULT if none." + (or (get sym tag) + (and def + (let ((plist (symbol-plist sym))) + (while (and plist (not (eq (car plist) tag))) + (setq plist (cdr (cdr plist)))) + (if plist (car (cdr plist)) def))))) + +(defun getf (plist tag &optional def) + "Search PROPLIST for property PROPNAME; return its value or DEFAULT. +PROPLIST is a list of the sort returned by `symbol-plist'." + (setplist '--cl-getf-symbol-- plist) + (or (get '--cl-getf-symbol-- tag) + (and def (get* '--cl-getf-symbol-- tag def)))) + +(defun cl-set-getf (plist tag val) + (let ((p plist)) + (while (and p (not (eq (car p) tag))) (setq p (cdr (cdr p)))) + (if p (progn (setcar (cdr p) val) plist) (list* tag val plist)))) + +(defun cl-do-remf (plist tag) + (let ((p (cdr plist))) + (while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p)))) + (and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t)))) + +(defun cl-remprop (sym tag) + "Remove from SYMBOL's plist the property PROP and its value." + (let ((plist (symbol-plist sym))) + (if (and plist (eq tag (car plist))) + (progn (setplist sym (cdr (cdr plist))) t) + (cl-do-remf plist tag)))) +(or (and (fboundp 'remprop) (subrp (symbol-function 'remprop))) + (defalias 'remprop 'cl-remprop)) + + + +;;; Hash tables. + +(defun make-hash-table (&rest cl-keys) + "Make an empty Common Lisp-style hash-table. +If :test is `eq', `eql', or `equal', this can use XEmacs built-in hash-tables. +In Emacs 19, or with a different test, this internally uses a-lists. +Keywords supported: :test :size +The Common Lisp keywords :rehash-size and :rehash-threshold are ignored." + (let ((cl-test (or (car (cdr (memq ':test cl-keys))) 'eql)) + (cl-size (or (car (cdr (memq ':size cl-keys))) 20))) + ;; XEmacs change + (if (and (memq cl-test '(eq eql equal)) (fboundp 'make-hashtable)) + (funcall 'make-hashtable cl-size cl-test) + (list 'cl-hash-table-tag cl-test + (if (> cl-size 1) (make-vector cl-size 0) + (let ((sym (make-symbol "--hashsym--"))) (set sym nil) sym)) + 0)))) + +(defvar cl-lucid-hash-tag + (if (and (fboundp 'make-hashtable) (vectorp (make-hashtable 1))) + (aref (make-hashtable 1) 0) (make-symbol "--cl-hash-tag--"))) + +(defun hash-table-p (x) + "Return t if OBJECT is a hash table." + (or (eq (car-safe x) 'cl-hash-table-tag) + (and (vectorp x) (= (length x) 4) (eq (aref x 0) cl-lucid-hash-tag)) + (and (fboundp 'hashtablep) (funcall 'hashtablep x)))) + +(defun cl-not-hash-table (x &optional y &rest z) + (signal 'wrong-type-argument (list 'hash-table-p (or y x)))) + +(defun cl-hash-lookup (key table) + (or (eq (car-safe table) 'cl-hash-table-tag) (cl-not-hash-table table)) + (let* ((array (nth 2 table)) (test (car (cdr table))) (str key) sym) + (if (symbolp array) (setq str nil sym (symbol-value array)) + (while (or (consp str) (and (vectorp str) (> (length str) 0))) + (setq str (elt str 0))) + (cond ((stringp str) (if (eq test 'equalp) (setq str (downcase str)))) + ((symbolp str) (setq str (symbol-name str))) + ((and (numberp str) (> str -8000000) (< str 8000000)) + (or (integerp str) (setq str (truncate str))) + (setq str (aref ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" + "11" "12" "13" "14" "15"] (logand str 15)))) + (t (setq str "*"))) + (setq sym (symbol-value (intern-soft str array)))) + (list (and sym (cond ((or (eq test 'eq) + (and (eq test 'eql) (not (numberp key)))) + (assq key sym)) + ((memq test '(eql equal)) (assoc key sym)) + (t (assoc* key sym ':test test)))) + sym str))) + +(defvar cl-builtin-gethash + (if (and (fboundp 'gethash) (subrp (symbol-function 'gethash))) + (symbol-function 'gethash) 'cl-not-hash-table)) +(defvar cl-builtin-remhash + (if (and (fboundp 'remhash) (subrp (symbol-function 'remhash))) + (symbol-function 'remhash) 'cl-not-hash-table)) +(defvar cl-builtin-clrhash + (if (and (fboundp 'clrhash) (subrp (symbol-function 'clrhash))) + (symbol-function 'clrhash) 'cl-not-hash-table)) +(defvar cl-builtin-maphash + (if (and (fboundp 'maphash) (subrp (symbol-function 'maphash))) + (symbol-function 'maphash) 'cl-not-hash-table)) + +(defun cl-gethash (key table &optional def) + "Look up KEY in HASH-TABLE; return corresponding value, or DEFAULT." + (if (consp table) + (let ((found (cl-hash-lookup key table))) + (if (car found) (cdr (car found)) def)) + (funcall cl-builtin-gethash key table def))) +(defalias 'gethash 'cl-gethash) + +(defun cl-puthash (key val table) + (if (consp table) + (let ((found (cl-hash-lookup key table))) + (if (car found) (setcdr (car found) val) + (if (nth 2 found) + (progn + (if (> (nth 3 table) (* (length (nth 2 table)) 3)) + (let ((new-table (make-vector (nth 3 table) 0))) + (mapatoms (function + (lambda (sym) + (set (intern (symbol-name sym) new-table) + (symbol-value sym)))) + (nth 2 table)) + (setcar (cdr (cdr table)) new-table))) + (set (intern (nth 2 found) (nth 2 table)) + (cons (cons key val) (nth 1 found)))) + (set (nth 2 table) (cons (cons key val) (nth 1 found)))) + (setcar (cdr (cdr (cdr table))) (1+ (nth 3 table))))) + (funcall 'puthash key val table)) val) + +(defun cl-remhash (key table) + "Remove KEY from HASH-TABLE." + (if (consp table) + (let ((found (cl-hash-lookup key table))) + (and (car found) + (let ((del (delq (car found) (nth 1 found)))) + (setcar (cdr (cdr (cdr table))) (1- (nth 3 table))) + (if (nth 2 found) (set (intern (nth 2 found) (nth 2 table)) del) + (set (nth 2 table) del)) t))) + (prog1 (not (eq (funcall cl-builtin-gethash key table '--cl--) '--cl--)) + (funcall cl-builtin-remhash key table)))) +(defalias 'remhash 'cl-remhash) + +(defun cl-clrhash (table) + "Clear HASH-TABLE." + (if (consp table) + (progn + (or (hash-table-p table) (cl-not-hash-table table)) + (if (symbolp (nth 2 table)) (set (nth 2 table) nil) + (setcar (cdr (cdr table)) (make-vector (length (nth 2 table)) 0))) + (setcar (cdr (cdr (cdr table))) 0)) + (funcall cl-builtin-clrhash table)) + nil) +(defalias 'clrhash 'cl-clrhash) + +(defun cl-maphash (cl-func cl-table) + "Call FUNCTION on keys and values from HASH-TABLE." + (or (hash-table-p cl-table) (cl-not-hash-table cl-table)) + (if (consp cl-table) + (mapatoms (function (lambda (cl-x) + (setq cl-x (symbol-value cl-x)) + (while cl-x + (funcall cl-func (car (car cl-x)) + (cdr (car cl-x))) + (setq cl-x (cdr cl-x))))) + (if (symbolp (nth 2 cl-table)) + (vector (nth 2 cl-table)) (nth 2 cl-table))) + (funcall cl-builtin-maphash cl-func cl-table))) +(defalias 'maphash 'cl-maphash) + +(defun hash-table-count (table) + "Return the number of entries in HASH-TABLE." + (or (hash-table-p table) (cl-not-hash-table table)) + (if (consp table) (nth 3 table) (funcall 'hashtable-fullness table))) + + +;;; Some debugging aids. + +(defun cl-prettyprint (form) + "Insert a pretty-printed rendition of a Lisp FORM in current buffer." + (let ((pt (point)) last) + (insert "\n" (prin1-to-string form) "\n") + (setq last (point)) + (goto-char (1+ pt)) + (while (search-forward "(quote " last t) + (delete-backward-char 7) + (insert "'") + (forward-sexp) + (delete-char 1)) + (goto-char (1+ pt)) + (cl-do-prettyprint))) + +(defun cl-do-prettyprint () + (skip-chars-forward " ") + (if (looking-at "(") + (let ((skip (or (looking-at "((") (looking-at "(prog") + (looking-at "(unwind-protect ") + (looking-at "(function (") + (looking-at "(cl-block-wrapper "))) + (two (or (looking-at "(defun ") (looking-at "(defmacro "))) + (let (or (looking-at "(let\\*? ") (looking-at "(while "))) + (set (looking-at "(p?set[qf] "))) + (if (or skip let + (progn + (forward-sexp) + (and (>= (current-column) 78) (progn (backward-sexp) t)))) + (let ((nl t)) + (forward-char 1) + (cl-do-prettyprint) + (or skip (looking-at ")") (cl-do-prettyprint)) + (or (not two) (looking-at ")") (cl-do-prettyprint)) + (while (not (looking-at ")")) + (if set (setq nl (not nl))) + (if nl (insert "\n")) + (lisp-indent-line) + (cl-do-prettyprint)) + (forward-char 1)))) + (forward-sexp))) + +(defvar cl-macroexpand-cmacs nil) +(defvar cl-closure-vars nil) + +(defun cl-macroexpand-all (form &optional env) + "Expand all macro calls through a Lisp FORM. +This also does some trivial optimizations to make the form prettier." + (while (or (not (eq form (setq form (macroexpand form env)))) + (and cl-macroexpand-cmacs + (not (eq form (setq form (compiler-macroexpand form))))))) + (cond ((not (consp form)) form) + ((memq (car form) '(let let*)) + (if (null (nth 1 form)) + (cl-macroexpand-all (cons 'progn (cddr form)) env) + (let ((letf nil) (res nil) (lets (cadr form))) + (while lets + (cl-push (if (consp (car lets)) + (let ((exp (cl-macroexpand-all (caar lets) env))) + (or (symbolp exp) (setq letf t)) + (cons exp (cl-macroexpand-body (cdar lets) env))) + (let ((exp (cl-macroexpand-all (car lets) env))) + (if (symbolp exp) exp + (setq letf t) (list exp nil)))) res) + (setq lets (cdr lets))) + (list* (if letf (if (eq (car form) 'let) 'letf 'letf*) (car form)) + (nreverse res) (cl-macroexpand-body (cddr form) env))))) + ((eq (car form) 'cond) + (cons (car form) + (mapcar (function (lambda (x) (cl-macroexpand-body x env))) + (cdr form)))) + ((eq (car form) 'condition-case) + (list* (car form) (nth 1 form) (cl-macroexpand-all (nth 2 form) env) + (mapcar (function + (lambda (x) + (cons (car x) (cl-macroexpand-body (cdr x) env)))) + (cdddr form)))) + ((memq (car form) '(quote function)) + (if (eq (car-safe (nth 1 form)) 'lambda) + (let ((body (cl-macroexpand-body (cddadr form) env))) + (if (and cl-closure-vars (eq (car form) 'function) + (cl-expr-contains-any body cl-closure-vars)) + (let* ((new (mapcar 'gensym cl-closure-vars)) + (sub (pairlis cl-closure-vars new)) (decls nil)) + (while (or (stringp (car body)) + (eq (car-safe (car body)) 'interactive)) + (cl-push (list 'quote (cl-pop body)) decls)) + (put (car (last cl-closure-vars)) 'used t) + (append + (list 'list '(quote lambda) '(quote (&rest --cl-rest--))) + (sublis sub (nreverse decls)) + (list + (list* 'list '(quote apply) + (list 'list '(quote quote) + (list 'function + (list* 'lambda + (append new (cadadr form)) + (sublis sub body)))) + (nconc (mapcar (function + (lambda (x) + (list 'list '(quote quote) x))) + cl-closure-vars) + '((quote --cl-rest--))))))) + (list (car form) (list* 'lambda (cadadr form) body)))) + (let ((found (assq (cadr form) env))) + (if (eq (cadr (caddr found)) 'cl-labels-args) + (cl-macroexpand-all (cadr (caddr (cadddr found))) env) + form)))) + ((memq (car form) '(defun defmacro)) + (list* (car form) (nth 1 form) (cl-macroexpand-body (cddr form) env))) + ((and (eq (car form) 'progn) (not (cddr form))) + (cl-macroexpand-all (nth 1 form) env)) + ((eq (car form) 'setq) + (let* ((args (cl-macroexpand-body (cdr form) env)) (p args)) + (while (and p (symbolp (car p))) (setq p (cddr p))) + (if p (cl-macroexpand-all (cons 'setf args)) (cons 'setq args)))) + (t (cons (car form) (cl-macroexpand-body (cdr form) env))))) + +(defun cl-macroexpand-body (body &optional env) + (mapcar (function (lambda (x) (cl-macroexpand-all x env))) body)) + +(defun cl-prettyexpand (form &optional full) + (message "Expanding...") + (let ((cl-macroexpand-cmacs full) (cl-compiling-file full) + (byte-compile-macro-environment nil)) + (setq form (cl-macroexpand-all form + (and (not full) '((block) (eval-when))))) + (message "Formatting...") + (prog1 (cl-prettyprint form) + (message "")))) + + + +(run-hooks 'cl-extra-load-hook) + +(provide 'cl-extra) + +;;; cl-extra.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl-macs.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cl-macs.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,2766 @@ +;;; cl-macs.el --- Common Lisp extensions for GNU Emacs Lisp (part four) + +;; Copyright (C) 1993 Free Software Foundation, Inc. + +;; Author: Dave Gillespie +;; Version: 2.02 +;; Keywords: extensions + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; These are extensions to Emacs Lisp that provide a degree of +;; Common Lisp compatibility, beyond what is already built-in +;; in Emacs Lisp. +;; +;; This package was written by Dave Gillespie; it is a complete +;; rewrite of Cesar Quiroz's original cl.el package of December 1986. +;; +;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. +;; +;; Bug reports, comments, and suggestions are welcome! + +;; This file contains the portions of the Common Lisp extensions +;; package which should be autoloaded, but need only be present +;; if the compiler or interpreter is used---this file is not +;; necessary for executing compiled code. + +;; See cl.el for Change Log. + + +;;; Code: + +(or (memq 'cl-19 features) + (error "Tried to load `cl-macs' before `cl'!")) + + +;;; We define these here so that this file can compile without having +;;; loaded the cl.el file already. + +(defmacro cl-push (x place) (list 'setq place (list 'cons x place))) +(defmacro cl-pop (place) + (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) +(defmacro cl-pop2 (place) + (list 'prog1 (list 'car (list 'cdr place)) + (list 'setq place (list 'cdr (list 'cdr place))))) +(put 'cl-push 'edebug-form-spec 'edebug-sexps) +(put 'cl-pop 'edebug-form-spec 'edebug-sexps) +(put 'cl-pop2 'edebug-form-spec 'edebug-sexps) + +(defvar cl-emacs-type) +(defvar cl-optimize-safety) +(defvar cl-optimize-speed) + + +;;; This kludge allows macros which use cl-transform-function-property +;;; to be called at compile-time. + +(require + (progn + (or (fboundp 'defalias) (fset 'defalias 'fset)) + (or (fboundp 'cl-transform-function-property) + (defalias 'cl-transform-function-property + (function (lambda (n p f) + (list 'put (list 'quote n) (list 'quote p) + (list 'function (cons 'lambda f))))))) + (car (or features (setq features (list 'cl-kludge)))))) + + +;;; Initialization. + +(defvar cl-old-bc-file-form nil) + +;; Patch broken Emacs 18 compiler (re top-level macros). +;; Emacs 19 compiler doesn't need this patch. +;; Also, undo broken definition of `eql' that uses same bytecode as `eq'. + +;;;###autoload +(defun cl-compile-time-init () + (setq cl-old-bc-file-form (symbol-function 'byte-compile-file-form)) + (or (fboundp 'byte-compile-flush-pending) ; Emacs 19 compiler? + (defalias 'byte-compile-file-form + (function + (lambda (form) + (setq form (macroexpand form byte-compile-macro-environment)) + (if (eq (car-safe form) 'progn) + (cons 'progn (mapcar 'byte-compile-file-form (cdr form))) + (funcall cl-old-bc-file-form form)))))) + (put 'eql 'byte-compile 'cl-byte-compile-compiler-macro) + (run-hooks 'cl-hack-bytecomp-hook)) + + +;;; Symbols. + +(defvar *gensym-counter*) + +;;;###autoload +(defun gensym (&optional arg) + "Generate a new uninterned symbol. +The name is made by appending a number to PREFIX, default \"G\"." + (let ((prefix (if (stringp arg) arg "G")) + (num (if (integerp arg) arg + (prog1 *gensym-counter* + (setq *gensym-counter* (1+ *gensym-counter*)))))) + (make-symbol (format "%s%d" prefix num)))) + +;;;###autoload +(defun gentemp (&optional arg) + "Generate a new interned symbol with a unique name. +The name is made by appending a number to PREFIX, default \"G\"." + (let ((prefix (if (stringp arg) arg "G")) + name) + (while (intern-soft (setq name (format "%s%d" prefix *gensym-counter*))) + (setq *gensym-counter* (1+ *gensym-counter*))) + (intern name))) + + +;;; Program structure. + +;;;###autoload +(defmacro defun* (name args &rest body) + "(defun* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. +Like normal `defun', except ARGLIST allows full Common Lisp conventions, +and BODY is implicitly surrounded by (block NAME ...)." + (let* ((res (cl-transform-lambda (cons args body) name)) + (form (list* 'defun name (cdr res)))) + (if (car res) (list 'progn (car res) form) form))) + +;;;###autoload +(defmacro defmacro* (name args &rest body) + "(defmacro* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a macro. +Like normal `defmacro', except ARGLIST allows full Common Lisp conventions, +and BODY is implicitly surrounded by (block NAME ...)." + (let* ((res (cl-transform-lambda (cons args body) name)) + (form (list* 'defmacro name (cdr res)))) + (if (car res) (list 'progn (car res) form) form))) + +;;;###autoload +(defmacro function* (func) + "(function* SYMBOL-OR-LAMBDA): introduce a function. +Like normal `function', except that if argument is a lambda form, its +ARGLIST allows full Common Lisp conventions." + (if (eq (car-safe func) 'lambda) + (let* ((res (cl-transform-lambda (cdr func) 'cl-none)) + (form (list 'function (cons 'lambda (cdr res))))) + (if (car res) (list 'progn (car res) form) form)) + (list 'function func))) + +(defun cl-transform-function-property (func prop form) + (let ((res (cl-transform-lambda form func))) + (append '(progn) (cdr (cdr (car res))) + (list (list 'put (list 'quote func) (list 'quote prop) + (list 'function (cons 'lambda (cdr res)))))))) + +(defconst lambda-list-keywords + '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) + +(defvar cl-macro-environment nil) +(defvar bind-block) (defvar bind-defs) (defvar bind-enquote) +(defvar bind-inits) (defvar bind-lets) (defvar bind-forms) + +(defun cl-transform-lambda (form bind-block) + (let* ((args (car form)) (body (cdr form)) + (bind-defs nil) (bind-enquote nil) + (bind-inits nil) (bind-lets nil) (bind-forms nil) + (header nil) (simple-args nil)) + (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) + (cl-push (cl-pop body) header)) + (setq args (if (listp args) (copy-list args) (list '&rest args))) + (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) + (if (setq bind-defs (cadr (memq '&cl-defs args))) + (setq args (delq '&cl-defs (delq bind-defs args)) + bind-defs (cadr bind-defs))) + (if (setq bind-enquote (memq '&cl-quote args)) + (setq args (delq '&cl-quote args))) + (if (memq '&whole args) (error "&whole not currently implemented")) + (let* ((p (memq '&environment args)) (v (cadr p))) + (if p (setq args (nconc (delq (car p) (delq v args)) + (list '&aux (list v 'cl-macro-environment)))))) + (while (and args (symbolp (car args)) + (not (memq (car args) '(nil &rest &body &key &aux))) + (not (and (eq (car args) '&optional) + (or bind-defs (consp (cadr args)))))) + (cl-push (cl-pop args) simple-args)) + (or (eq bind-block 'cl-none) + (setq body (list (list* 'block bind-block body)))) + (if (null args) + (list* nil (nreverse simple-args) (nconc (nreverse header) body)) + (if (memq '&optional simple-args) (cl-push '&optional args)) + (cl-do-arglist args nil (- (length simple-args) + (if (memq '&optional simple-args) 1 0))) + (setq bind-lets (nreverse bind-lets)) + (list* (and bind-inits (list* 'eval-when '(compile load eval) + (nreverse bind-inits))) + (nconc (nreverse simple-args) + (list '&rest (car (cl-pop bind-lets)))) + (nconc (nreverse header) + (list (nconc (list 'let* bind-lets) + (nreverse bind-forms) body))))))) + +(defun cl-do-arglist (args expr &optional num) ; uses bind-* + (if (nlistp args) + (if (or (memq args lambda-list-keywords) (not (symbolp args))) + (error "Invalid argument name: %s" args) + (cl-push (list args expr) bind-lets)) + (setq args (copy-list args)) + (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) + (let ((p (memq '&body args))) (if p (setcar p '&rest))) + (if (memq '&environment args) (error "&environment used incorrectly")) + (let ((save-args args) + (restarg (memq '&rest args)) + (safety (if (cl-compiling-file) cl-optimize-safety 3)) + (keys nil) + (laterarg nil) (exactarg nil) minarg) + (or num (setq num 0)) + (if (listp (cadr restarg)) + (setq restarg (gensym "--rest--")) + (setq restarg (cadr restarg))) + (cl-push (list restarg expr) bind-lets) + (if (eq (car args) '&whole) + (cl-push (list (cl-pop2 args) restarg) bind-lets)) + (let ((p args)) + (setq minarg restarg) + (while (and p (not (memq (car p) lambda-list-keywords))) + (or (eq p args) (setq minarg (list 'cdr minarg))) + (setq p (cdr p))) + (if (memq (car p) '(nil &aux)) + (setq minarg (list '= (list 'length restarg) + (length (ldiff args p))) + exactarg (not (eq args p))))) + (while (and args (not (memq (car args) lambda-list-keywords))) + (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car) + restarg))) + (cl-do-arglist + (cl-pop args) + (if (or laterarg (= safety 0)) poparg + (list 'if minarg poparg + (list 'signal '(quote wrong-number-of-arguments) + (list 'list (and (not (eq bind-block 'cl-none)) + (list 'quote bind-block)) + (list 'length restarg))))))) + (setq num (1+ num) laterarg t)) + (while (and (eq (car args) '&optional) (cl-pop args)) + (while (and args (not (memq (car args) lambda-list-keywords))) + (let ((arg (cl-pop args))) + (or (consp arg) (setq arg (list arg))) + (if (cddr arg) (cl-do-arglist (nth 2 arg) (list 'and restarg t))) + (let ((def (if (cdr arg) (nth 1 arg) + (or (car bind-defs) + (nth 1 (assq (car arg) bind-defs))))) + (poparg (list 'pop restarg))) + (and def bind-enquote (setq def (list 'quote def))) + (cl-do-arglist (car arg) + (if def (list 'if restarg poparg def) poparg)) + (setq num (1+ num)))))) + (if (eq (car args) '&rest) + (let ((arg (cl-pop2 args))) + (if (consp arg) (cl-do-arglist arg restarg))) + (or (eq (car args) '&key) (= safety 0) exactarg + (cl-push (list 'if restarg + (list 'signal '(quote wrong-number-of-arguments) + (list 'list + (and (not (eq bind-block 'cl-none)) + (list 'quote bind-block)) + (list '+ num (list 'length restarg))))) + bind-forms))) + (while (and (eq (car args) '&key) (cl-pop args)) + (while (and args (not (memq (car args) lambda-list-keywords))) + (let ((arg (cl-pop args))) + (or (consp arg) (setq arg (list arg))) + (let* ((karg (if (consp (car arg)) (caar arg) + (intern (format ":%s" (car arg))))) + (varg (if (consp (car arg)) (cadar arg) (car arg))) + (def (if (cdr arg) (cadr arg) + (or (car bind-defs) (cadr (assq varg bind-defs))))) + (look (list 'memq (list 'quote karg) restarg))) + (and def bind-enquote (setq def (list 'quote def))) + (if (cddr arg) + (let* ((temp (or (nth 2 arg) (gensym))) + (val (list 'car (list 'cdr temp)))) + (cl-do-arglist temp look) + (cl-do-arglist varg + (list 'if temp + (list 'prog1 val (list 'setq temp t)) + def))) + (cl-do-arglist + varg + (list 'car + (list 'cdr + (if (null def) + look + (list 'or look + (if (eq (cl-const-expr-p def) t) + (list + 'quote + (list nil (cl-const-expr-val def))) + (list 'list nil def)))))))) + (cl-push karg keys) + (if (= (aref (symbol-name karg) 0) ?:) + (progn (set karg karg) + (cl-push (list 'setq karg (list 'quote karg)) + bind-inits))))))) + (setq keys (nreverse keys)) + (or (and (eq (car args) '&allow-other-keys) (cl-pop args)) + (null keys) (= safety 0) + (let* ((var (gensym "--keys--")) + (allow '(:allow-other-keys)) + (check (list + 'while var + (list + 'cond + (list (list 'memq (list 'car var) + (list 'quote (append keys allow))) + (list 'setq var (list 'cdr (list 'cdr var)))) + (list (list 'car + (list 'cdr + (list 'memq (cons 'quote allow) + restarg))) + (list 'setq var nil)) + (list t + (list + 'error + (format "Keyword argument %%s not one of %s" + keys) + (list 'car var))))))) + (cl-push (list 'let (list (list var restarg)) check) bind-forms))) + (while (and (eq (car args) '&aux) (cl-pop args)) + (while (and args (not (memq (car args) lambda-list-keywords))) + (if (consp (car args)) + (if (and bind-enquote (cadar args)) + (cl-do-arglist (caar args) + (list 'quote (cadr (cl-pop args)))) + (cl-do-arglist (caar args) (cadr (cl-pop args)))) + (cl-do-arglist (cl-pop args) nil)))) + (if args (error "Malformed argument list %s" save-args))))) + +(defun cl-arglist-args (args) + (if (nlistp args) (list args) + (let ((res nil) (kind nil) arg) + (while (consp args) + (setq arg (cl-pop args)) + (if (memq arg lambda-list-keywords) (setq kind arg) + (if (eq arg '&cl-defs) (cl-pop args) + (and (consp arg) kind (setq arg (car arg))) + (and (consp arg) (cdr arg) (eq kind '&key) (setq arg (cadr arg))) + (setq res (nconc res (cl-arglist-args arg)))))) + (nconc res (and args (list args)))))) + +;;;###autoload +(defmacro destructuring-bind (args expr &rest body) + (let* ((bind-lets nil) (bind-forms nil) (bind-inits nil) + (bind-defs nil) (bind-block 'cl-none)) + (cl-do-arglist (or args '(&aux)) expr) + (append '(progn) bind-inits + (list (nconc (list 'let* (nreverse bind-lets)) + (nreverse bind-forms) body))))) + + +;;; The `eval-when' form. + +(defvar cl-not-toplevel nil) + +;;;###autoload +(defmacro eval-when (when &rest body) + "(eval-when (WHEN...) BODY...): control when BODY is evaluated. +If `compile' is in WHEN, BODY is evaluated when compiled at top-level. +If `load' is in WHEN, BODY is evaluated when loaded after top-level compile. +If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level." + (if (and (fboundp 'cl-compiling-file) (cl-compiling-file) + (not cl-not-toplevel) (not (boundp 'for-effect))) ; horrible kludge + (let ((comp (or (memq 'compile when) (memq ':compile-toplevel when))) + (cl-not-toplevel t)) + (if (or (memq 'load when) (memq ':load-toplevel when)) + (if comp (cons 'progn (mapcar 'cl-compile-time-too body)) + (list* 'if nil nil body)) + (progn (if comp (eval (cons 'progn body))) nil))) + (and (or (memq 'eval when) (memq ':execute when)) + (cons 'progn body)))) + +(defun cl-compile-time-too (form) + (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler)) + (setq form (macroexpand + form (cons '(eval-when) byte-compile-macro-environment)))) + (cond ((eq (car-safe form) 'progn) + (cons 'progn (mapcar 'cl-compile-time-too (cdr form)))) + ((eq (car-safe form) 'eval-when) + (let ((when (nth 1 form))) + (if (or (memq 'eval when) (memq ':execute when)) + (list* 'eval-when (cons 'compile when) (cddr form)) + form))) + (t (eval form) form))) + +(or (and (fboundp 'eval-when-compile) + (not (eq (car-safe (symbol-function 'eval-when-compile)) 'autoload))) + (eval '(defmacro eval-when-compile (&rest body) + "Like `progn', but evaluates the body at compile time. +The result of the body appears to the compiler as a quoted constant." + (list 'quote (eval (cons 'progn body)))))) + +;;;###autoload +(defmacro load-time-value (form &optional read-only) + "Like `progn', but evaluates the body at load time. +The result of the body appears to the compiler as a quoted constant." + (if (cl-compiling-file) + (let* ((temp (gentemp "--cl-load-time--")) + (set (list 'set (list 'quote temp) form))) + (if (and (fboundp 'byte-compile-file-form-defmumble) + (boundp 'this-kind) (boundp 'that-one)) + (fset 'byte-compile-file-form + (list 'lambda '(form) + (list 'fset '(quote byte-compile-file-form) + (list 'quote + (symbol-function 'byte-compile-file-form))) + (list 'byte-compile-file-form (list 'quote set)) + '(byte-compile-file-form form))) + ;; XEmacs change + (print set (symbol-value ;;'outbuffer + 'byte-compile-output-buffer + ))) + (list 'symbol-value (list 'quote temp))) + (list 'quote (eval form)))) + + +;;; Conditional control structures. + +;;;###autoload +(defmacro case (expr &rest clauses) + "(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. +Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared +against each key in each KEYLIST; the corresponding BODY is evaluated. +If no clause succeeds, case returns nil. A single atom may be used in +place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is +allowed only in the final clause, and matches if no other keys match. +Key values are compared by `eql'." + (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) + (head-list nil) + (body (cons + 'cond + (mapcar + (function + (lambda (c) + (cons (cond ((memq (car c) '(t otherwise)) t) + ((eq (car c) 'ecase-error-flag) + (list 'error "ecase failed: %s, %s" + temp (list 'quote (reverse head-list)))) + ((listp (car c)) + (setq head-list (append (car c) head-list)) + (list 'member* temp (list 'quote (car c)))) + (t + (if (memq (car c) head-list) + (error "Duplicate key in case: %s" + (car c))) + (cl-push (car c) head-list) + (list 'eql temp (list 'quote (car c))))) + (or (cdr c) '(nil))))) + clauses)))) + (if (eq temp expr) body + (list 'let (list (list temp expr)) body)))) + +;;;###autoload +(defmacro ecase (expr &rest clauses) + "(ecase EXPR CLAUSES...): like `case', but error if no case fits. +`otherwise'-clauses are not allowed." + (list* 'case expr (append clauses '((ecase-error-flag))))) + +;;;###autoload +(defmacro typecase (expr &rest clauses) + "(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. +Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it +satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, +typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the +final clause, and matches if no other keys match." + (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) + (type-list nil) + (body (cons + 'cond + (mapcar + (function + (lambda (c) + (cons (cond ((eq (car c) 'otherwise) t) + ((eq (car c) 'ecase-error-flag) + (list 'error "etypecase failed: %s, %s" + temp (list 'quote (reverse type-list)))) + (t + (cl-push (car c) type-list) + (cl-make-type-test temp (car c)))) + (or (cdr c) '(nil))))) + clauses)))) + (if (eq temp expr) body + (list 'let (list (list temp expr)) body)))) + +;;;###autoload +(defmacro etypecase (expr &rest clauses) + "(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits. +`otherwise'-clauses are not allowed." + (list* 'typecase expr (append clauses '((ecase-error-flag))))) + + +;;; Blocks and exits. + +;;;###autoload +(defmacro block (name &rest body) + "(block NAME BODY...): define a lexically-scoped block named NAME. +NAME may be any symbol. Code inside the BODY forms can call `return-from' +to jump prematurely out of the block. This differs from `catch' and `throw' +in two respects: First, the NAME is an unevaluated symbol rather than a +quoted symbol or other form; and second, NAME is lexically rather than +dynamically scoped: Only references to it within BODY will work. These +references may appear inside macro expansions, but not inside functions +called from BODY." + (if (cl-safe-expr-p (cons 'progn body)) (cons 'progn body) + (list 'cl-block-wrapper + (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name))) + body)))) + +(defvar cl-active-block-names nil) + +(put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block) +(defun cl-byte-compile-block (cl-form) + (if (fboundp 'byte-compile-form-do-effect) ; Check for optimizing compiler + (progn + (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil)) + (cl-active-block-names (cons cl-entry cl-active-block-names)) + (cl-body (byte-compile-top-level + (cons 'progn (cddr (nth 1 cl-form)))))) + (if (cdr cl-entry) + (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) cl-body)) + (byte-compile-form cl-body)))) + (byte-compile-form (nth 1 cl-form)))) + +(put 'cl-block-throw 'byte-compile 'cl-byte-compile-throw) +(defun cl-byte-compile-throw (cl-form) + (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names))) + (if cl-found (setcdr cl-found t))) + (byte-compile-normal-call (cons 'throw (cdr cl-form)))) + +;;;###autoload +(defmacro return (&optional res) + "(return [RESULT]): return from the block named nil. +This is equivalent to `(return-from nil RESULT)'." + (list 'return-from nil res)) + +;;;###autoload +(defmacro return-from (name &optional res) + "(return-from NAME [RESULT]): return from the block named NAME. +This jump out to the innermost enclosing `(block NAME ...)' form, +returning RESULT from that form (or nil if RESULT is omitted). +This is compatible with Common Lisp, but note that `defun' and +`defmacro' do not create implicit blocks as they do in Common Lisp." + (let ((name2 (intern (format "--cl-block-%s--" name)))) + (list 'cl-block-throw (list 'quote name2) res))) + + +;;; The "loop" macro. + +(defvar args) (defvar loop-accum-var) (defvar loop-accum-vars) +(defvar loop-bindings) (defvar loop-body) (defvar loop-destr-temps) +(defvar loop-finally) (defvar loop-finish-flag) (defvar loop-first-flag) +(defvar loop-initially) (defvar loop-map-form) (defvar loop-name) +(defvar loop-result) (defvar loop-result-explicit) +(defvar loop-result-var) (defvar loop-steps) (defvar loop-symbol-macs) + +;;;###autoload +(defmacro loop (&rest args) + "(loop CLAUSE...): The Common Lisp `loop' macro. +Valid clauses are: + for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, + for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, + for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, + always COND, never COND, thereis COND, collect EXPR into VAR, + append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, + count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, + if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], + unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], + do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, + finally return EXPR, named NAME." + (if (not (memq t (mapcar 'symbolp (delq nil (delq t (copy-list args)))))) + (list 'block nil (list* 'while t args)) + (let ((loop-name nil) (loop-bindings nil) + (loop-body nil) (loop-steps nil) + (loop-result nil) (loop-result-explicit nil) + (loop-result-var nil) (loop-finish-flag nil) + (loop-accum-var nil) (loop-accum-vars nil) + (loop-initially nil) (loop-finally nil) + (loop-map-form nil) (loop-first-flag nil) + (loop-destr-temps nil) (loop-symbol-macs nil)) + (setq args (append args '(cl-end-loop))) + (while (not (eq (car args) 'cl-end-loop)) (cl-parse-loop-clause)) + (if loop-finish-flag + (cl-push (list (list loop-finish-flag t)) loop-bindings)) + (if loop-first-flag + (progn (cl-push (list (list loop-first-flag t)) loop-bindings) + (cl-push (list 'setq loop-first-flag nil) loop-steps))) + (let* ((epilogue (nconc (nreverse loop-finally) + (list (or loop-result-explicit loop-result)))) + (ands (cl-loop-build-ands (nreverse loop-body))) + (while-body (nconc (cadr ands) (nreverse loop-steps))) + (body (append + (nreverse loop-initially) + (list (if loop-map-form + (list 'block '--cl-finish-- + (subst + (if (eq (car ands) t) while-body + (cons (list 'or (car ands) + '(return-from --cl-finish-- + nil)) + while-body)) + '--cl-map loop-map-form)) + (list* 'while (car ands) while-body))) + (if loop-finish-flag + (if (equal epilogue '(nil)) (list loop-result-var) + (list (list 'if loop-finish-flag + (cons 'progn epilogue) loop-result-var))) + epilogue)))) + (if loop-result-var (cl-push (list loop-result-var) loop-bindings)) + (while loop-bindings + (if (cdar loop-bindings) + (setq body (list (cl-loop-let (cl-pop loop-bindings) body t))) + (let ((lets nil)) + (while (and loop-bindings + (not (cdar loop-bindings))) + (cl-push (car (cl-pop loop-bindings)) lets)) + (setq body (list (cl-loop-let lets body nil)))))) + (if loop-symbol-macs + (setq body (list (list* 'symbol-macrolet loop-symbol-macs body)))) + (list* 'block loop-name body))))) + +(defun cl-parse-loop-clause () ; uses args, loop-* + (let ((word (cl-pop args)) + (hash-types '(hash-key hash-keys hash-value hash-values)) + (key-types '(key-code key-codes key-seq key-seqs + key-binding key-bindings))) + (cond + + ((null args) + (error "Malformed `loop' macro")) + + ((eq word 'named) + (setq loop-name (cl-pop args))) + + ((eq word 'initially) + (if (memq (car args) '(do doing)) (cl-pop args)) + (or (consp (car args)) (error "Syntax error on `initially' clause")) + (while (consp (car args)) + (cl-push (cl-pop args) loop-initially))) + + ((eq word 'finally) + (if (eq (car args) 'return) + (setq loop-result-explicit (or (cl-pop2 args) '(quote nil))) + (if (memq (car args) '(do doing)) (cl-pop args)) + (or (consp (car args)) (error "Syntax error on `finally' clause")) + (if (and (eq (caar args) 'return) (null loop-name)) + (setq loop-result-explicit (or (nth 1 (cl-pop args)) '(quote nil))) + (while (consp (car args)) + (cl-push (cl-pop args) loop-finally))))) + + ((memq word '(for as)) + (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil) + (ands nil)) + (while + (let ((var (or (cl-pop args) (gensym)))) + (setq word (cl-pop args)) + (if (eq word 'being) (setq word (cl-pop args))) + (if (memq word '(the each)) (setq word (cl-pop args))) + (if (memq word '(buffer buffers)) + (setq word 'in args (cons '(buffer-list) args))) + (cond + + ((memq word '(from downfrom upfrom to downto upto + above below by)) + (cl-push word args) + (if (memq (car args) '(downto above)) + (error "Must specify `from' value for downward loop")) + (let* ((down (or (eq (car args) 'downfrom) + (memq (caddr args) '(downto above)))) + (excl (or (memq (car args) '(above below)) + (memq (caddr args) '(above below)))) + (start (and (memq (car args) '(from upfrom downfrom)) + (cl-pop2 args))) + (end (and (memq (car args) + '(to upto downto above below)) + (cl-pop2 args))) + (step (and (eq (car args) 'by) (cl-pop2 args))) + (end-var (and (not (cl-const-expr-p end)) (gensym))) + (step-var (and (not (cl-const-expr-p step)) + (gensym)))) + (and step (numberp step) (<= step 0) + (error "Loop `by' value is not positive: %s" step)) + (cl-push (list var (or start 0)) loop-for-bindings) + (if end-var (cl-push (list end-var end) loop-for-bindings)) + (if step-var (cl-push (list step-var step) + loop-for-bindings)) + (if end + (cl-push (list + (if down (if excl '> '>=) (if excl '< '<=)) + var (or end-var end)) loop-body)) + (cl-push (list var (list (if down '- '+) var + (or step-var step 1))) + loop-for-steps))) + + ((memq word '(in in-ref on)) + (let* ((on (eq word 'on)) + (temp (if (and on (symbolp var)) var (gensym)))) + (cl-push (list temp (cl-pop args)) loop-for-bindings) + (cl-push (list 'consp temp) loop-body) + (if (eq word 'in-ref) + (cl-push (list var (list 'car temp)) loop-symbol-macs) + (or (eq temp var) + (progn + (cl-push (list var nil) loop-for-bindings) + (cl-push (list var (if on temp (list 'car temp))) + loop-for-sets)))) + (cl-push (list temp + (if (eq (car args) 'by) + (let ((step (cl-pop2 args))) + (if (and (memq (car-safe step) + '(quote function + function*)) + (symbolp (nth 1 step))) + (list (nth 1 step) temp) + (list 'funcall step temp))) + (list 'cdr temp))) + loop-for-steps))) + + ((eq word '=) + (let* ((start (cl-pop args)) + (then (if (eq (car args) 'then) (cl-pop2 args) start))) + (cl-push (list var nil) loop-for-bindings) + (if (or ands (eq (car args) 'and)) + (progn + (cl-push (list var + (list 'if + (or loop-first-flag + (setq loop-first-flag + (gensym))) + start var)) + loop-for-sets) + (cl-push (list var then) loop-for-steps)) + (cl-push (list var + (if (eq start then) start + (list 'if + (or loop-first-flag + (setq loop-first-flag (gensym))) + start then))) + loop-for-sets)))) + + ((memq word '(across across-ref)) + (let ((temp-vec (gensym)) (temp-idx (gensym))) + (cl-push (list temp-vec (cl-pop args)) loop-for-bindings) + (cl-push (list temp-idx -1) loop-for-bindings) + (cl-push (list '< (list 'setq temp-idx (list '1+ temp-idx)) + (list 'length temp-vec)) loop-body) + (if (eq word 'across-ref) + (cl-push (list var (list 'aref temp-vec temp-idx)) + loop-symbol-macs) + (cl-push (list var nil) loop-for-bindings) + (cl-push (list var (list 'aref temp-vec temp-idx)) + loop-for-sets)))) + + ((memq word '(element elements)) + (let ((ref (or (memq (car args) '(in-ref of-ref)) + (and (not (memq (car args) '(in of))) + (error "Expected `of'")))) + (seq (cl-pop2 args)) + (temp-seq (gensym)) + (temp-idx (if (eq (car args) 'using) + (if (and (= (length (cadr args)) 2) + (eq (caadr args) 'index)) + (cadr (cl-pop2 args)) + (error "Bad `using' clause")) + (gensym)))) + (cl-push (list temp-seq seq) loop-for-bindings) + (cl-push (list temp-idx 0) loop-for-bindings) + (if ref + (let ((temp-len (gensym))) + (cl-push (list temp-len (list 'length temp-seq)) + loop-for-bindings) + (cl-push (list var (list 'elt temp-seq temp-idx)) + loop-symbol-macs) + (cl-push (list '< temp-idx temp-len) loop-body)) + (cl-push (list var nil) loop-for-bindings) + (cl-push (list 'and temp-seq + (list 'or (list 'consp temp-seq) + (list '< temp-idx + (list 'length temp-seq)))) + loop-body) + (cl-push (list var (list 'if (list 'consp temp-seq) + (list 'pop temp-seq) + (list 'aref temp-seq temp-idx))) + loop-for-sets)) + (cl-push (list temp-idx (list '1+ temp-idx)) + loop-for-steps))) + + ((memq word hash-types) + (or (memq (car args) '(in of)) (error "Expected `of'")) + (let* ((table (cl-pop2 args)) + (other (if (eq (car args) 'using) + (if (and (= (length (cadr args)) 2) + (memq (caadr args) hash-types) + (not (eq (caadr args) word))) + (cadr (cl-pop2 args)) + (error "Bad `using' clause")) + (gensym)))) + (if (memq word '(hash-value hash-values)) + (setq var (prog1 other (setq other var)))) + (setq loop-map-form + (list 'maphash (list 'function + (list* 'lambda (list var other) + '--cl-map)) table)))) + + ((memq word '(symbol present-symbol external-symbol + symbols present-symbols external-symbols)) + (let ((ob (and (memq (car args) '(in of)) (cl-pop2 args)))) + (setq loop-map-form + (list 'mapatoms (list 'function + (list* 'lambda (list var) + '--cl-map)) ob)))) + + ((memq word '(overlay overlays extent extents)) + (let ((buf nil) (from nil) (to nil)) + (while (memq (car args) '(in of from to)) + (cond ((eq (car args) 'from) (setq from (cl-pop2 args))) + ((eq (car args) 'to) (setq to (cl-pop2 args))) + (t (setq buf (cl-pop2 args))))) + (setq loop-map-form + (list 'cl-map-extents + (list 'function (list 'lambda (list var (gensym)) + '(progn . --cl-map) nil)) + buf from to)))) + + ((memq word '(interval intervals)) + (let ((buf nil) (prop nil) (from nil) (to nil) + (var1 (gensym)) (var2 (gensym))) + (while (memq (car args) '(in of property from to)) + (cond ((eq (car args) 'from) (setq from (cl-pop2 args))) + ((eq (car args) 'to) (setq to (cl-pop2 args))) + ((eq (car args) 'property) + (setq prop (cl-pop2 args))) + (t (setq buf (cl-pop2 args))))) + (if (and (consp var) (symbolp (car var)) (symbolp (cdr var))) + (setq var1 (car var) var2 (cdr var)) + (cl-push (list var (list 'cons var1 var2)) loop-for-sets)) + (setq loop-map-form + (list 'cl-map-intervals + (list 'function (list 'lambda (list var1 var2) + '(progn . --cl-map))) + buf prop from to)))) + + ((memq word key-types) + (or (memq (car args) '(in of)) (error "Expected `of'")) + (let ((map (cl-pop2 args)) + (other (if (eq (car args) 'using) + (if (and (= (length (cadr args)) 2) + (memq (caadr args) key-types) + (not (eq (caadr args) word))) + (cadr (cl-pop2 args)) + (error "Bad `using' clause")) + (gensym)))) + (if (memq word '(key-binding key-bindings)) + (setq var (prog1 other (setq other var)))) + (setq loop-map-form + (list (if (memq word '(key-seq key-seqs)) + 'cl-map-keymap-recursively 'cl-map-keymap) + (list 'function (list* 'lambda (list var other) + '--cl-map)) map)))) + + ((memq word '(frame frames screen screens)) + (let ((temp (gensym))) + (cl-push (list var (if (eq cl-emacs-type 'lucid) + '(selected-screen) '(selected-frame))) + loop-for-bindings) + (cl-push (list temp nil) loop-for-bindings) + (cl-push (list 'prog1 (list 'not (list 'eq var temp)) + (list 'or temp (list 'setq temp var))) + loop-body) + (cl-push (list var (list (if (eq cl-emacs-type 'lucid) + 'next-screen 'next-frame) var)) + loop-for-steps))) + + ((memq word '(window windows)) + (let ((scr (and (memq (car args) '(in of)) (cl-pop2 args))) + (temp (gensym))) + (cl-push (list var (if scr + (list (if (eq cl-emacs-type 'lucid) + 'screen-selected-window + 'frame-selected-window) scr) + '(selected-window))) + loop-for-bindings) + (cl-push (list temp nil) loop-for-bindings) + (cl-push (list 'prog1 (list 'not (list 'eq var temp)) + (list 'or temp (list 'setq temp var))) + loop-body) + (cl-push (list var (list 'next-window var)) loop-for-steps))) + + (t + (let ((handler (and (symbolp word) + (get word 'cl-loop-for-handler)))) + (if handler + (funcall handler var) + (error "Expected a `for' preposition, found %s" word))))) + (eq (car args) 'and)) + (setq ands t) + (cl-pop args)) + (if (and ands loop-for-bindings) + (cl-push (nreverse loop-for-bindings) loop-bindings) + (setq loop-bindings (nconc (mapcar 'list loop-for-bindings) + loop-bindings))) + (if loop-for-sets + (cl-push (list 'progn + (cl-loop-let (nreverse loop-for-sets) 'setq ands) + t) loop-body)) + (if loop-for-steps + (cl-push (cons (if ands 'psetq 'setq) + (apply 'append (nreverse loop-for-steps))) + loop-steps)))) + + ((eq word 'repeat) + (let ((temp (gensym))) + (cl-push (list (list temp (cl-pop args))) loop-bindings) + (cl-push (list '>= (list 'setq temp (list '1- temp)) 0) loop-body))) + + ((eq word 'collect) + (let ((what (cl-pop args)) + (var (cl-loop-handle-accum nil 'nreverse))) + (if (eq var loop-accum-var) + (cl-push (list 'progn (list 'push what var) t) loop-body) + (cl-push (list 'progn + (list 'setq var (list 'nconc var (list 'list what))) + t) loop-body)))) + + ((memq word '(nconc nconcing append appending)) + (let ((what (cl-pop args)) + (var (cl-loop-handle-accum nil 'nreverse))) + (cl-push (list 'progn + (list 'setq var + (if (eq var loop-accum-var) + (list 'nconc + (list (if (memq word '(nconc nconcing)) + 'nreverse 'reverse) + what) + var) + (list (if (memq word '(nconc nconcing)) + 'nconc 'append) + var what))) t) loop-body))) + + ((memq word '(concat concating)) + (let ((what (cl-pop args)) + (var (cl-loop-handle-accum ""))) + (cl-push (list 'progn (list 'callf 'concat var what) t) loop-body))) + + ((memq word '(vconcat vconcating)) + (let ((what (cl-pop args)) + (var (cl-loop-handle-accum []))) + (cl-push (list 'progn (list 'callf 'vconcat var what) t) loop-body))) + + ((memq word '(sum summing)) + (let ((what (cl-pop args)) + (var (cl-loop-handle-accum 0))) + (cl-push (list 'progn (list 'incf var what) t) loop-body))) + + ((memq word '(count counting)) + (let ((what (cl-pop args)) + (var (cl-loop-handle-accum 0))) + (cl-push (list 'progn (list 'if what (list 'incf var)) t) loop-body))) + + ((memq word '(minimize minimizing maximize maximizing)) + (let* ((what (cl-pop args)) + (temp (if (cl-simple-expr-p what) what (gensym))) + (var (cl-loop-handle-accum nil)) + (func (intern (substring (symbol-name word) 0 3))) + (set (list 'setq var (list 'if var (list func var temp) temp)))) + (cl-push (list 'progn (if (eq temp what) set + (list 'let (list (list temp what)) set)) + t) loop-body))) + + ((eq word 'with) + (let ((bindings nil)) + (while (progn (cl-push (list (cl-pop args) + (and (eq (car args) '=) (cl-pop2 args))) + bindings) + (eq (car args) 'and)) + (cl-pop args)) + (cl-push (nreverse bindings) loop-bindings))) + + ((eq word 'while) + (cl-push (cl-pop args) loop-body)) + + ((eq word 'until) + (cl-push (list 'not (cl-pop args)) loop-body)) + + ((eq word 'always) + (or loop-finish-flag (setq loop-finish-flag (gensym))) + (cl-push (list 'setq loop-finish-flag (cl-pop args)) loop-body) + (setq loop-result t)) + + ((eq word 'never) + (or loop-finish-flag (setq loop-finish-flag (gensym))) + (cl-push (list 'setq loop-finish-flag (list 'not (cl-pop args))) + loop-body) + (setq loop-result t)) + + ((eq word 'thereis) + (or loop-finish-flag (setq loop-finish-flag (gensym))) + (or loop-result-var (setq loop-result-var (gensym))) + (cl-push (list 'setq loop-finish-flag + (list 'not (list 'setq loop-result-var (cl-pop args)))) + loop-body)) + + ((memq word '(if when unless)) + (let* ((cond (cl-pop args)) + (then (let ((loop-body nil)) + (cl-parse-loop-clause) + (cl-loop-build-ands (nreverse loop-body)))) + (else (let ((loop-body nil)) + (if (eq (car args) 'else) + (progn (cl-pop args) (cl-parse-loop-clause))) + (cl-loop-build-ands (nreverse loop-body)))) + (simple (and (eq (car then) t) (eq (car else) t)))) + (if (eq (car args) 'end) (cl-pop args)) + (if (eq word 'unless) (setq then (prog1 else (setq else then)))) + (let ((form (cons (if simple (cons 'progn (nth 1 then)) (nth 2 then)) + (if simple (nth 1 else) (list (nth 2 else)))))) + (if (cl-expr-contains form 'it) + (let ((temp (gensym))) + (cl-push (list temp) loop-bindings) + (setq form (list* 'if (list 'setq temp cond) + (subst temp 'it form)))) + (setq form (list* 'if cond form))) + (cl-push (if simple (list 'progn form t) form) loop-body)))) + + ((memq word '(do doing)) + (let ((body nil)) + (or (consp (car args)) (error "Syntax error on `do' clause")) + (while (consp (car args)) (cl-push (cl-pop args) body)) + (cl-push (cons 'progn (nreverse (cons t body))) loop-body))) + + ((eq word 'return) + (or loop-finish-flag (setq loop-finish-flag (gensym))) + (or loop-result-var (setq loop-result-var (gensym))) + (cl-push (list 'setq loop-result-var (cl-pop args) + loop-finish-flag nil) loop-body)) + + (t + (let ((handler (and (symbolp word) (get word 'cl-loop-handler)))) + (or handler (error "Expected a loop keyword, found %s" word)) + (funcall handler)))) + (if (eq (car args) 'and) + (progn (cl-pop args) (cl-parse-loop-clause))))) + +(defun cl-loop-let (specs body par) ; uses loop-* + (let ((p specs) (temps nil) (new nil)) + (while (and p (or (symbolp (car-safe (car p))) (null (cadar p)))) + (setq p (cdr p))) + (and par p + (progn + (setq par nil p specs) + (while p + (or (cl-const-expr-p (cadar p)) + (let ((temp (gensym))) + (cl-push (list temp (cadar p)) temps) + (setcar (cdar p) temp))) + (setq p (cdr p))))) + (while specs + (if (and (consp (car specs)) (listp (caar specs))) + (let* ((spec (caar specs)) (nspecs nil) + (expr (cadr (cl-pop specs))) + (temp (cdr (or (assq spec loop-destr-temps) + (car (cl-push (cons spec (or (last spec 0) + (gensym))) + loop-destr-temps)))))) + (cl-push (list temp expr) new) + (while (consp spec) + (cl-push (list (cl-pop spec) + (and expr (list (if spec 'pop 'car) temp))) + nspecs)) + (setq specs (nconc (nreverse nspecs) specs))) + (cl-push (cl-pop specs) new))) + (if (eq body 'setq) + (let ((set (cons (if par 'psetq 'setq) (apply 'nconc (nreverse new))))) + (if temps (list 'let* (nreverse temps) set) set)) + (list* (if par 'let 'let*) + (nconc (nreverse temps) (nreverse new)) body)))) + +(defun cl-loop-handle-accum (def &optional func) ; uses args, loop-* + (if (eq (car args) 'into) + (let ((var (cl-pop2 args))) + (or (memq var loop-accum-vars) + (progn (cl-push (list (list var def)) loop-bindings) + (cl-push var loop-accum-vars))) + var) + (or loop-accum-var + (progn + (cl-push (list (list (setq loop-accum-var (gensym)) def)) + loop-bindings) + (setq loop-result (if func (list func loop-accum-var) + loop-accum-var)) + loop-accum-var)))) + +(defun cl-loop-build-ands (clauses) + (let ((ands nil) + (body nil)) + (while clauses + (if (and (eq (car-safe (car clauses)) 'progn) + (eq (car (last (car clauses))) t)) + (if (cdr clauses) + (setq clauses (cons (nconc (butlast (car clauses)) + (if (eq (car-safe (cadr clauses)) + 'progn) + (cdadr clauses) + (list (cadr clauses)))) + (cddr clauses))) + (setq body (cdr (butlast (cl-pop clauses))))) + (cl-push (cl-pop clauses) ands))) + (setq ands (or (nreverse ands) (list t))) + (list (if (cdr ands) (cons 'and ands) (car ands)) + body + (let ((full (if body + (append ands (list (cons 'progn (append body '(t))))) + ands))) + (if (cdr full) (cons 'and full) (car full)))))) + + +;;; Other iteration control structures. + +;;;###autoload +(defmacro do (steps endtest &rest body) + "The Common Lisp `do' loop. +Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" + (cl-expand-do-loop steps endtest body nil)) + +;;;###autoload +(defmacro do* (steps endtest &rest body) + "The Common Lisp `do*' loop. +Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" + (cl-expand-do-loop steps endtest body t)) + +(defun cl-expand-do-loop (steps endtest body star) + (list 'block nil + (list* (if star 'let* 'let) + (mapcar (function (lambda (c) + (if (consp c) (list (car c) (nth 1 c)) c))) + steps) + (list* 'while (list 'not (car endtest)) + (append body + (let ((sets (mapcar + (function + (lambda (c) + (and (consp c) (cdr (cdr c)) + (list (car c) (nth 2 c))))) + steps))) + (setq sets (delq nil sets)) + (and sets + (list (cons (if (or star (not (cdr sets))) + 'setq 'psetq) + (apply 'append sets))))))) + (or (cdr endtest) '(nil))))) + +;;;###autoload +(defmacro dolist (spec &rest body) + "(dolist (VAR LIST [RESULT]) BODY...): loop over a list. +Evaluate BODY with VAR bound to each `car' from LIST, in turn. +Then evaluate RESULT to get return value, default nil." + (let ((temp (gensym "--dolist-temp--"))) + (list 'block nil + (list* 'let (list (list temp (nth 1 spec)) (car spec)) + (list* 'while temp (list 'setq (car spec) (list 'car temp)) + (append body (list (list 'setq temp + (list 'cdr temp))))) + (if (cdr (cdr spec)) + (cons (list 'setq (car spec) nil) (cdr (cdr spec))) + '(nil)))))) + +;;;###autoload +(defmacro dotimes (spec &rest body) + "(dotimes (VAR COUNT [RESULT]) BODY...): loop a certain number of times. +Evaluate BODY with VAR bound to successive integers from 0, inclusive, +to COUNT, exclusive. Then evaluate RESULT to get return value, default +nil." + (let ((temp (gensym "--dotimes-temp--"))) + (list 'block nil + (list* 'let (list (list temp (nth 1 spec)) (list (car spec) 0)) + (list* 'while (list '< (car spec) temp) + (append body (list (list 'incf (car spec))))) + (or (cdr (cdr spec)) '(nil)))))) + +;;;###autoload +(defmacro do-symbols (spec &rest body) + "(dosymbols (VAR [OBARRAY [RESULT]]) BODY...): loop over all symbols. +Evaluate BODY with VAR bound to each interned symbol, or to each symbol +from OBARRAY." + ;; Apparently this doesn't have an implicit block. + (list 'block nil + (list 'let (list (car spec)) + (list* 'mapatoms + (list 'function (list* 'lambda (list (car spec)) body)) + (and (cadr spec) (list (cadr spec)))) + (caddr spec)))) + +;;;###autoload +(defmacro do-all-symbols (spec &rest body) + (list* 'do-symbols (list (car spec) nil (cadr spec)) body)) + + +;;; Assignments. + +;;;###autoload +(defmacro psetq (&rest args) + "(psetq SYM VAL SYM VAL ...): set SYMs to the values VALs in parallel. +This is like `setq', except that all VAL forms are evaluated (in order) +before assigning any symbols SYM to the corresponding values." + (cons 'psetf args)) + + +;;; Binding control structures. + +;;;###autoload +(defmacro progv (symbols values &rest body) + "(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY. +The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. +Each SYMBOL in the first list is bound to the corresponding VALUE in the +second list (or made unbound if VALUES is shorter than SYMBOLS); then the +BODY forms are executed and their result is returned. This is much like +a `let' form, except that the list of symbols can be computed at run-time." + (list 'let '((cl-progv-save nil)) + (list 'unwind-protect + (list* 'progn (list 'cl-progv-before symbols values) body) + '(cl-progv-after)))) + +;;; This should really have some way to shadow 'byte-compile properties, etc. +;;;###autoload +(defmacro flet (bindings &rest body) + "(flet ((FUNC ARGLIST BODY...) ...) FORM...): make temporary function defns. +This is an analogue of `let' that operates on the function cell of FUNC +rather than its value cell. The FORMs are evaluated with the specified +function definitions in place, then the definitions are undone (the FUNCs +go back to their previous definitions, or lack thereof)." + (list* 'letf* + (mapcar + (function + (lambda (x) + (if (or (and (fboundp (car x)) + (eq (car-safe (symbol-function (car x))) 'macro)) + (cdr (assq (car x) cl-macro-environment))) + (error "Use `labels', not `flet', to rebind macro names")) + (let ((func (list 'function* + (list 'lambda (cadr x) + (list* 'block (car x) (cddr x)))))) + (if (and (cl-compiling-file) + (boundp 'byte-compile-function-environment)) + (cl-push (cons (car x) (eval func)) + byte-compile-function-environment)) + (list (list 'symbol-function (list 'quote (car x))) func)))) + bindings) + body)) + +;;;###autoload +(defmacro labels (bindings &rest body) + "(labels ((FUNC ARGLIST BODY...) ...) FORM...): make temporary func bindings. +This is like `flet', except the bindings are lexical instead of dynamic. +Unlike `flet', this macro is fully complaint with the Common Lisp standard." + (let ((vars nil) (sets nil) (cl-macro-environment cl-macro-environment)) + (while bindings + (let ((var (gensym))) + (cl-push var vars) + (cl-push (list 'function* (cons 'lambda (cdar bindings))) sets) + (cl-push var sets) + (cl-push (list (car (cl-pop bindings)) 'lambda '(&rest cl-labels-args) + (list 'list* '(quote funcall) (list 'quote var) + 'cl-labels-args)) + cl-macro-environment))) + (cl-macroexpand-all (list* 'lexical-let vars (cons (cons 'setq sets) body)) + cl-macro-environment))) + +;; The following ought to have a better definition for use with newer +;; byte compilers. +;;;###autoload +(defmacro macrolet (bindings &rest body) + "(macrolet ((NAME ARGLIST BODY...) ...) FORM...): make temporary macro defns. +This is like `flet', but for macros instead of functions." + (if (cdr bindings) + (list 'macrolet + (list (car bindings)) (list* 'macrolet (cdr bindings) body)) + (if (null bindings) (cons 'progn body) + (let* ((name (caar bindings)) + (res (cl-transform-lambda (cdar bindings) name))) + (eval (car res)) + (cl-macroexpand-all (cons 'progn body) + (cons (list* name 'lambda (cdr res)) + cl-macro-environment)))))) + +;;;###autoload +(defmacro symbol-macrolet (bindings &rest body) + "(symbol-macrolet ((NAME EXPANSION) ...) FORM...): make symbol macro defns. +Within the body FORMs, references to the variable NAME will be replaced +by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)." + (if (cdr bindings) + (list 'symbol-macrolet + (list (car bindings)) (list* 'symbol-macrolet (cdr bindings) body)) + (if (null bindings) (cons 'progn body) + (cl-macroexpand-all (cons 'progn body) + (cons (list (symbol-name (caar bindings)) + (cadar bindings)) + cl-macro-environment))))) + +(defvar cl-closure-vars nil) +;;;###autoload +(defmacro lexical-let (bindings &rest body) + "(lexical-let BINDINGS BODY...): like `let', but lexically scoped. +The main visible difference is that lambdas inside BODY will create +lexical closures as in Common Lisp." + (let* ((cl-closure-vars cl-closure-vars) + (vars (mapcar (function + (lambda (x) + (or (consp x) (setq x (list x))) + (cl-push (gensym (format "--%s--" (car x))) + cl-closure-vars) + (list (car x) (cadr x) (car cl-closure-vars)))) + bindings)) + (ebody + (cl-macroexpand-all + (cons 'progn body) + (nconc (mapcar (function (lambda (x) + (list (symbol-name (car x)) + (list 'symbol-value (caddr x)) + t))) vars) + (list '(defun . cl-defun-expander)) + cl-macro-environment)))) + (if (not (get (car (last cl-closure-vars)) 'used)) + (list 'let (mapcar (function (lambda (x) + (list (caddr x) (cadr x)))) vars) + (sublis (mapcar (function (lambda (x) + (cons (caddr x) + (list 'quote (caddr x))))) + vars) + ebody)) + (list 'let (mapcar (function (lambda (x) + (list (caddr x) + (list 'make-symbol + (format "--%s--" (car x)))))) + vars) + (apply 'append '(setf) + (mapcar (function + (lambda (x) + (list (list 'symbol-value (caddr x)) (cadr x)))) + vars)) + ebody)))) + +;;;###autoload +(defmacro lexical-let* (bindings &rest body) + "(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped. +The main visible difference is that lambdas inside BODY will create +lexical closures as in Common Lisp." + (if (null bindings) (cons 'progn body) + (setq bindings (reverse bindings)) + (while bindings + (setq body (list (list* 'lexical-let (list (cl-pop bindings)) body)))) + (car body))) + +(defun cl-defun-expander (func &rest rest) + (list 'progn + (list 'defalias (list 'quote func) + (list 'function (cons 'lambda rest))) + (list 'quote func))) + + +;;; Multiple values. + +;;;###autoload +(defmacro multiple-value-bind (vars form &rest body) + "(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values. +FORM must return a list; the BODY is then executed with the first N elements +of this list bound (`let'-style) to each of the symbols SYM in turn. This +is analogous to the Common Lisp `multiple-value-bind' macro, using lists to +simulate true multiple return values. For compatibility, (values A B C) is +a synonym for (list A B C)." + (let ((temp (gensym)) (n -1)) + (list* 'let* (cons (list temp form) + (mapcar (function + (lambda (v) + (list v (list 'nth (setq n (1+ n)) temp)))) + vars)) + body))) + +;;;###autoload +(defmacro multiple-value-setq (vars form) + "(multiple-value-setq (SYM SYM...) FORM): collect multiple return values. +FORM must return a list; the first N elements of this list are stored in +each of the symbols SYM in turn. This is analogous to the Common Lisp +`multiple-value-setq' macro, using lists to simulate true multiple return +values. For compatibility, (values A B C) is a synonym for (list A B C)." + (cond ((null vars) (list 'progn form nil)) + ((null (cdr vars)) (list 'setq (car vars) (list 'car form))) + (t + (let* ((temp (gensym)) (n 0)) + (list 'let (list (list temp form)) + (list 'prog1 (list 'setq (cl-pop vars) (list 'car temp)) + (cons 'setq (apply 'nconc + (mapcar (function + (lambda (v) + (list v (list + 'nth + (setq n (1+ n)) + temp)))) + vars))))))))) + + +;;; Declarations. + +;;;###autoload +(defmacro locally (&rest body) (cons 'progn body)) +;;;###autoload +(defmacro the (type form) form) + +(defvar cl-proclaim-history t) ; for future compilers +(defvar cl-declare-stack t) ; for future compilers + +(defun cl-do-proclaim (spec hist) + (and hist (listp cl-proclaim-history) (cl-push spec cl-proclaim-history)) + (cond ((eq (car-safe spec) 'special) + (if (boundp 'byte-compile-bound-variables) + (setq byte-compile-bound-variables + ;; todo: this should compute correct binding bits vs. 0 + (append (mapcar #'(lambda (v) (cons v 0)) + (cdr spec)) + byte-compile-bound-variables)))) + + ((eq (car-safe spec) 'inline) + (while (setq spec (cdr spec)) + (or (memq (get (car spec) 'byte-optimizer) + '(nil byte-compile-inline-expand)) + (error "%s already has a byte-optimizer, can't make it inline" + (car spec))) + (put (car spec) 'byte-optimizer 'byte-compile-inline-expand))) + + ((eq (car-safe spec) 'notinline) + (while (setq spec (cdr spec)) + (if (eq (get (car spec) 'byte-optimizer) + 'byte-compile-inline-expand) + (put (car spec) 'byte-optimizer nil)))) + + ((eq (car-safe spec) 'optimize) + (let ((speed (assq (nth 1 (assq 'speed (cdr spec))) + '((0 nil) (1 t) (2 t) (3 t)))) + (safety (assq (nth 1 (assq 'safety (cdr spec))) + '((0 t) (1 t) (2 t) (3 nil))))) + (if speed (setq cl-optimize-speed (car speed) + byte-optimize (nth 1 speed))) + (if safety (setq cl-optimize-safety (car safety) + byte-compile-delete-errors (nth 1 safety))))) + + ((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings)) + (if (eq byte-compile-warnings t) + ;; XEmacs change + (setq byte-compile-warnings byte-compile-default-warnings)) + (while (setq spec (cdr spec)) + (if (consp (car spec)) + (if (eq (cadar spec) 0) + (setq byte-compile-warnings + (delq (caar spec) byte-compile-warnings)) + (setq byte-compile-warnings + (adjoin (caar spec) byte-compile-warnings))))))) + nil) + +;;; Process any proclamations made before cl-macs was loaded. +(defvar cl-proclaims-deferred) +(let ((p (reverse cl-proclaims-deferred))) + (while p (cl-do-proclaim (cl-pop p) t)) + (setq cl-proclaims-deferred nil)) + +;;;###autoload +(defmacro declare (&rest specs) + (if (cl-compiling-file) + (while specs + (if (listp cl-declare-stack) (cl-push (car specs) cl-declare-stack)) + (cl-do-proclaim (cl-pop specs) nil))) + nil) + + + +;;; Generalized variables. + +;;;###autoload +(defmacro define-setf-method (func args &rest body) + "(define-setf-method NAME ARGLIST BODY...): define a `setf' method. +This method shows how to handle `setf's to places of the form (NAME ARGS...). +The argument forms ARGS are bound according to ARGLIST, as if NAME were +going to be expanded as a macro, then the BODY forms are executed and must +return a list of five elements: a temporary-variables list, a value-forms +list, a store-variables list (of length one), a store-form, and an access- +form. See `defsetf' for a simpler way to define most setf-methods." + (append '(eval-when (compile load eval)) + (if (stringp (car body)) + (list (list 'put (list 'quote func) '(quote setf-documentation) + (cl-pop body)))) + (list (cl-transform-function-property + func 'setf-method (cons args body))))) + +;;;###autoload +(defmacro defsetf (func arg1 &rest args) + "(defsetf NAME FUNC): define a `setf' method. +This macro is an easy-to-use substitute for `define-setf-method' that works +well for simple place forms. In the simple `defsetf' form, `setf's of +the form (setf (NAME ARGS...) VAL) are transformed to function or macro +calls of the form (FUNC ARGS... VAL). Example: (defsetf aref aset). +Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). +Here, the above `setf' call is expanded by binding the argument forms ARGS +according to ARGLIST, binding the value form VAL to STORE, then executing +BODY, which must return a Lisp form that does the necessary `setf' operation. +Actually, ARGLIST and STORE may be bound to temporary variables which are +introduced automatically to preserve proper execution order of the arguments. +Example: (defsetf nth (n x) (v) (list 'setcar (list 'nthcdr n x) v))." + (if (listp arg1) + (let* ((largs nil) (largsr nil) + (temps nil) (tempsr nil) + (restarg nil) (rest-temps nil) + (store-var (car (prog1 (car args) (setq args (cdr args))))) + (store-temp (intern (format "--%s--temp--" store-var))) + (lets1 nil) (lets2 nil) + (docstr nil) (p arg1)) + (if (stringp (car args)) + (setq docstr (prog1 (car args) (setq args (cdr args))))) + (while (and p (not (eq (car p) '&aux))) + (if (eq (car p) '&rest) + (setq p (cdr p) restarg (car p)) + (or (memq (car p) '(&optional &key &allow-other-keys)) + (setq largs (cons (if (consp (car p)) (car (car p)) (car p)) + largs) + temps (cons (intern (format "--%s--temp--" (car largs))) + temps)))) + (setq p (cdr p))) + (setq largs (nreverse largs) temps (nreverse temps)) + (if restarg + (setq largsr (append largs (list restarg)) + rest-temps (intern (format "--%s--temp--" restarg)) + tempsr (append temps (list rest-temps))) + (setq largsr largs tempsr temps)) + (let ((p1 largs) (p2 temps)) + (while p1 + (setq lets1 (cons (list (car p2) + (list 'gensym (format "--%s--" (car p1)))) + lets1) + lets2 (cons (list (car p1) (car p2)) lets2) + p1 (cdr p1) p2 (cdr p2)))) + (if restarg (setq lets2 (cons (list restarg rest-temps) lets2))) + (append (list 'define-setf-method func arg1) + (and docstr (list docstr)) + (list + (list 'let* + (nreverse + (cons (list store-temp + (list 'gensym (format "--%s--" store-var))) + (if restarg + (append + (list + (list rest-temps + (list 'mapcar '(quote gensym) + restarg))) + lets1) + lets1))) + (list 'list ; 'values + (cons (if restarg 'list* 'list) tempsr) + (cons (if restarg 'list* 'list) largsr) + (list 'list store-temp) + (cons 'let* + (cons (nreverse + (cons (list store-var store-temp) + lets2)) + args)) + (cons (if restarg 'list* 'list) + (cons (list 'quote func) tempsr))))))) + (list 'defsetf func '(&rest args) '(store) + (let ((call (list 'cons (list 'quote arg1) + '(append args (list store))))) + (if (car args) + (list 'list '(quote progn) call 'store) + call))))) + +;;; Some standard place types from Common Lisp. +(defsetf aref aset) +(defsetf car setcar) +(defsetf cdr setcdr) +(defsetf elt (seq n) (store) + (list 'if (list 'listp seq) (list 'setcar (list 'nthcdr n seq) store) + (list 'aset seq n store))) +(defsetf get (x y &optional d) (store) (list 'put x y store)) +(defsetf get* (x y &optional d) (store) (list 'put x y store)) +(defsetf gethash (x h &optional d) (store) (list 'cl-puthash x store h)) +(defsetf nth (n x) (store) (list 'setcar (list 'nthcdr n x) store)) +(defsetf subseq (seq start &optional end) (new) + (list 'progn (list 'replace seq new ':start1 start ':end1 end) new)) +(defsetf symbol-function fset) +(defsetf symbol-plist setplist) +(defsetf symbol-value set) + +;;; Various car/cdr aliases. Note that `cadr' is handled specially. +(defsetf first setcar) +(defsetf second (x) (store) (list 'setcar (list 'cdr x) store)) +(defsetf third (x) (store) (list 'setcar (list 'cddr x) store)) +(defsetf fourth (x) (store) (list 'setcar (list 'cdddr x) store)) +(defsetf fifth (x) (store) (list 'setcar (list 'nthcdr 4 x) store)) +(defsetf sixth (x) (store) (list 'setcar (list 'nthcdr 5 x) store)) +(defsetf seventh (x) (store) (list 'setcar (list 'nthcdr 6 x) store)) +(defsetf eighth (x) (store) (list 'setcar (list 'nthcdr 7 x) store)) +(defsetf ninth (x) (store) (list 'setcar (list 'nthcdr 8 x) store)) +(defsetf tenth (x) (store) (list 'setcar (list 'nthcdr 9 x) store)) +(defsetf rest setcdr) + +;;; Some more Emacs-related place types. +(defsetf buffer-file-name set-visited-file-name t) +(defsetf buffer-modified-p set-buffer-modified-p t) +(defsetf buffer-name rename-buffer t) +(defsetf buffer-string () (store) + (list 'progn '(erase-buffer) (list 'insert store))) +(defsetf buffer-substring cl-set-buffer-substring) +(defsetf current-buffer set-buffer) +(defsetf current-case-table set-case-table) +(defsetf current-column move-to-column t) +(defsetf current-global-map use-global-map t) +(defsetf current-input-mode () (store) + (list 'progn (list 'apply 'set-input-mode store) store)) +(defsetf current-local-map use-local-map t) +(defsetf current-window-configuration set-window-configuration t) +(defsetf default-file-modes set-default-file-modes t) +(defsetf default-value set-default) +(defsetf documentation-property put) +(defsetf extent-data set-extent-data) ; obsolete +(defsetf extent-face set-extent-face) +(defsetf extent-priority set-extent-priority) +(defsetf extent-property (x y &optional d) (arg) + (list 'set-extent-property x y arg)) +(defsetf extent-end-position (ext) (store) + (list 'progn (list 'set-extent-endpoints (list 'extent-start-position ext) + store) store)) +(defsetf extent-start-position (ext) (store) + (list 'progn (list 'set-extent-endpoints store + (list 'extent-end-position ext)) store)) +(defsetf face-background (f &optional s) (x) (list 'set-face-background f x s)) +(defsetf face-background-pixmap (f &optional s) (x) + (list 'set-face-background-pixmap f x s)) +(defsetf face-font (f &optional s) (x) (list 'set-face-font f x s)) +(defsetf face-foreground (f &optional s) (x) (list 'set-face-foreground f x s)) +(defsetf face-underline-p (f &optional s) (x) + (list 'set-face-underline-p f x s)) +(defsetf file-modes set-file-modes t) +(defsetf frame-parameters modify-frame-parameters t) +(defsetf frame-visible-p cl-set-frame-visible-p) +(defsetf frame-properties (&optional f) (p) + `(progn (set-frame-properties ,f ,p) ,p)) +(defsetf frame-property (f p &optional d) (v) + `(progn (set-frame-property ,f ,v) ,p)) +(defsetf frame-width (&optional f) (v) + `(progn (set-frame-width ,f ,v) ,v)) +(defsetf frame-height (&optional f) (v) + `(progn (set-frame-height ,f ,v) ,v)) +(defsetf current-frame-configuration set-frame-configuration) + +;; XEmacs: new stuff +;; Consoles +(defsetf selected-console select-console t) +(defsetf selected-device select-device t) +(defsetf device-baud-rate (&optional d) (v) + `(set-device-baud-rate ,d ,v)) +(defsetf specifier-instance (spec &optional dom def nof) (val) + `(set-specifier ,spec ,val ,dom)) + +;; Annotations +(defsetf annotation-glyph set-annotation-glyph) +(defsetf annotation-down-glyph set-annotation-down-glyph) +(defsetf annotation-face set-annotation-face) +(defsetf annotation-layout set-annotation-layout) +(defsetf annotation-data set-annotation-data) +(defsetf annotation-action set-annotation-action) +(defsetf annotation-menu set-annotation-menu) +;; Widget +(defsetf widget-get widget-put t) +(defsetf widget-value widget-value-set t) + +;; Misc +(defsetf recent-keys-ring-size set-recent-keys-ring-size) +(defsetf symbol-value-in-buffer (s b &optional u) (store) + `(with-current-buffer ,b (set ,s ,store))) +(defsetf symbol-value-in-console (s c &optional u) (store) + `(letf (((selected-console) ,c)) + (set ,s ,store))) + +(defsetf getenv setenv t) +(defsetf get-register set-register) +(defsetf global-key-binding global-set-key) +(defsetf keymap-parent set-keymap-parent) +(defsetf keymap-name set-keymap-name) +(defsetf keymap-prompt set-keymap-prompt) +(defsetf keymap-default-binding set-keymap-default-binding) +(defsetf local-key-binding local-set-key) +(defsetf mark set-mark t) +(defsetf mark-marker set-mark t) +(defsetf marker-position set-marker t) +(defsetf match-data store-match-data t) +(defsetf mouse-position (scr) (store) + (list 'set-mouse-position scr (list 'car store) (list 'cadr store) + (list 'cddr store))) +(defsetf overlay-get overlay-put) +(defsetf overlay-start (ov) (store) + (list 'progn (list 'move-overlay ov store (list 'overlay-end ov)) store)) +(defsetf overlay-end (ov) (store) + (list 'progn (list 'move-overlay ov (list 'overlay-start ov) store) store)) +(defsetf point goto-char) +(defsetf point-marker goto-char t) +(defsetf point-max () (store) + (list 'progn (list 'narrow-to-region '(point-min) store) store)) +(defsetf point-min () (store) + (list 'progn (list 'narrow-to-region store '(point-max)) store)) +(defsetf process-buffer set-process-buffer) +(defsetf process-filter set-process-filter) +(defsetf process-sentinel set-process-sentinel) +(defsetf read-mouse-position (scr) (store) + (list 'set-mouse-position scr (list 'car store) (list 'cdr store))) +(defsetf screen-height set-screen-height t) +(defsetf screen-width set-screen-width t) +(defsetf selected-window select-window) +(defsetf selected-screen select-screen) +(defsetf selected-frame select-frame) +(defsetf standard-case-table set-standard-case-table) +(defsetf syntax-table set-syntax-table) +(defsetf visited-file-modtime set-visited-file-modtime t) +(defsetf window-buffer set-window-buffer t) +(defsetf window-display-table set-window-display-table t) +(defsetf window-dedicated-p set-window-dedicated-p t) +(defsetf window-height () (store) + (list 'progn (list 'enlarge-window (list '- store '(window-height))) store)) +(defsetf window-hscroll set-window-hscroll) +(defsetf window-point set-window-point) +(defsetf window-start set-window-start) +(defsetf window-width () (store) + (list 'progn (list 'enlarge-window (list '- store '(window-width)) t) store)) +(defsetf x-get-cutbuffer x-store-cutbuffer t) +(defsetf x-get-cut-buffer x-store-cut-buffer t) ; groan. +(defsetf x-get-secondary-selection x-own-secondary-selection t) +(defsetf x-get-selection x-own-selection t) + +;;; More complex setf-methods. +;;; These should take &environment arguments, but since full arglists aren't +;;; available while compiling cl-macs, we fake it by referring to the global +;;; variable cl-macro-environment directly. + +(define-setf-method apply (func arg1 &rest rest) + (or (and (memq (car-safe func) '(quote function function*)) + (symbolp (car-safe (cdr-safe func)))) + (error "First arg to apply in setf is not (function SYM): %s" func)) + (let* ((form (cons (nth 1 func) (cons arg1 rest))) + (method (get-setf-method form cl-macro-environment))) + (list (car method) (nth 1 method) (nth 2 method) + (cl-setf-make-apply (nth 3 method) (cadr func) (car method)) + (cl-setf-make-apply (nth 4 method) (cadr func) (car method))))) + +(defun cl-setf-make-apply (form func temps) + (if (eq (car form) 'progn) + (list* 'progn (cl-setf-make-apply (cadr form) func temps) (cddr form)) + (or (equal (last form) (last temps)) + (error "%s is not suitable for use with setf-of-apply" func)) + (list* 'apply (list 'quote (car form)) (cdr form)))) + +(define-setf-method nthcdr (n place) + (let ((method (get-setf-method place cl-macro-environment)) + (n-temp (gensym "--nthcdr-n--")) + (store-temp (gensym "--nthcdr-store--"))) + (list (cons n-temp (car method)) + (cons n (nth 1 method)) + (list store-temp) + (list 'let (list (list (car (nth 2 method)) + (list 'cl-set-nthcdr n-temp (nth 4 method) + store-temp))) + (nth 3 method) store-temp) + (list 'nthcdr n-temp (nth 4 method))))) + +(define-setf-method getf (place tag &optional def) + (let ((method (get-setf-method place cl-macro-environment)) + (tag-temp (gensym "--getf-tag--")) + (def-temp (gensym "--getf-def--")) + (store-temp (gensym "--getf-store--"))) + (list (append (car method) (list tag-temp def-temp)) + (append (nth 1 method) (list tag def)) + (list store-temp) + (list 'let (list (list (car (nth 2 method)) + (list 'cl-set-getf (nth 4 method) + tag-temp store-temp))) + (nth 3 method) store-temp) + (list 'getf (nth 4 method) tag-temp def-temp)))) + +(define-setf-method substring (place from &optional to) + (let ((method (get-setf-method place cl-macro-environment)) + (from-temp (gensym "--substring-from--")) + (to-temp (gensym "--substring-to--")) + (store-temp (gensym "--substring-store--"))) + (list (append (car method) (list from-temp to-temp)) + (append (nth 1 method) (list from to)) + (list store-temp) + (list 'let (list (list (car (nth 2 method)) + (list 'cl-set-substring (nth 4 method) + from-temp to-temp store-temp))) + (nth 3 method) store-temp) + (list 'substring (nth 4 method) from-temp to-temp)))) + +(define-setf-method values (&rest args) + (let ((methods (mapcar #'(lambda (x) + (get-setf-method x cl-macro-environment)) + args)) + (store-temp (gensym "--values-store--"))) + (list (apply 'append (mapcar 'first methods)) + (apply 'append (mapcar 'second methods)) + (list store-temp) + (cons 'list + (mapcar #'(lambda (m) + (cl-setf-do-store (cons (car (third m)) (fourth m)) + (list 'pop store-temp))) + methods)) + (cons 'list (mapcar 'fifth methods))))) + +;;; Getting and optimizing setf-methods. +;;;###autoload +(defun get-setf-method (place &optional env) + "Return a list of five values describing the setf-method for PLACE. +PLACE may be any Lisp form which can appear as the PLACE argument to +a macro like `setf' or `incf'." + (if (symbolp place) + (let ((temp (gensym "--setf--"))) + (list nil nil (list temp) (list 'setq place temp) place)) + (or (and (symbolp (car place)) + (let* ((func (car place)) + (name (symbol-name func)) + (method (get func 'setf-method)) + (case-fold-search nil)) + (or (and method + (let ((cl-macro-environment env)) + (setq method (apply method (cdr place)))) + (if (and (consp method) (= (length method) 5)) + method + (error "Setf-method for %s returns malformed method" + func))) + (and (save-match-data + (string-match "\\`c[ad][ad][ad]?[ad]?r\\'" name)) + (get-setf-method (compiler-macroexpand place))) + (and (eq func 'edebug-after) + (get-setf-method (nth (1- (length place)) place) + env))))) + (if (eq place (setq place (macroexpand place env))) + (if (and (symbolp (car place)) (fboundp (car place)) + (symbolp (symbol-function (car place)))) + (get-setf-method (cons (symbol-function (car place)) + (cdr place)) env) + (error "No setf-method known for %s" (car place))) + (get-setf-method place env))))) + +(defun cl-setf-do-modify (place opt-expr) + (let* ((method (get-setf-method place cl-macro-environment)) + (temps (car method)) (values (nth 1 method)) + (lets nil) (subs nil) + (optimize (and (not (eq opt-expr 'no-opt)) + (or (and (not (eq opt-expr 'unsafe)) + (cl-safe-expr-p opt-expr)) + (cl-setf-simple-store-p (car (nth 2 method)) + (nth 3 method))))) + (simple (and optimize (consp place) (cl-simple-exprs-p (cdr place))))) + (while values + (if (or simple (cl-const-expr-p (car values))) + (cl-push (cons (cl-pop temps) (cl-pop values)) subs) + (cl-push (list (cl-pop temps) (cl-pop values)) lets))) + (list (nreverse lets) + (cons (car (nth 2 method)) (sublis subs (nth 3 method))) + (sublis subs (nth 4 method))))) + +(defun cl-setf-do-store (spec val) + (let ((sym (car spec)) + (form (cdr spec))) + (if (or (cl-const-expr-p val) + (and (cl-simple-expr-p val) (eq (cl-expr-contains form sym) 1)) + (cl-setf-simple-store-p sym form)) + (subst val sym form) + (list 'let (list (list sym val)) form)))) + +(defun cl-setf-simple-store-p (sym form) + (and (consp form) (eq (cl-expr-contains form sym) 1) + (eq (nth (1- (length form)) form) sym) + (symbolp (car form)) (fboundp (car form)) + (not (eq (car-safe (symbol-function (car form))) 'macro)))) + +;;; The standard modify macros. +;;;###autoload +(defmacro setf (&rest args) + "(setf PLACE VAL PLACE VAL ...): set each PLACE to the value of its VAL. +This is a generalized version of `setq'; the PLACEs may be symbolic +references such as (car x) or (aref x i), as well as plain symbols. +For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y). +The return value is the last VAL in the list." + (if (cdr (cdr args)) + (let ((sets nil)) + (while args (cl-push (list 'setf (cl-pop args) (cl-pop args)) sets)) + (cons 'progn (nreverse sets))) + (if (symbolp (car args)) + (and args (cons 'setq args)) + (let* ((method (cl-setf-do-modify (car args) (nth 1 args))) + (store (cl-setf-do-store (nth 1 method) (nth 1 args)))) + (if (car method) (list 'let* (car method) store) store))))) + +;;;###autoload +(defmacro psetf (&rest args) + "(psetf PLACE VAL PLACE VAL ...): set PLACEs to the values VALs in parallel. +This is like `setf', except that all VAL forms are evaluated (in order) +before assigning any PLACEs to the corresponding values." + (let ((p args) (simple t) (vars nil)) + (while p + (if (or (not (symbolp (car p))) (cl-expr-depends-p (nth 1 p) vars)) + (setq simple nil)) + (if (memq (car p) vars) + (error "Destination duplicated in psetf: %s" (car p))) + (cl-push (cl-pop p) vars) + (or p (error "Odd number of arguments to psetf")) + (cl-pop p)) + (if simple + (list 'progn (cons 'setf args) nil) + (setq args (reverse args)) + (let ((expr (list 'setf (cadr args) (car args)))) + (while (setq args (cddr args)) + (setq expr (list 'setf (cadr args) (list 'prog1 (car args) expr)))) + (list 'progn expr nil))))) + +;;;###autoload +(defun cl-do-pop (place) + (if (cl-simple-expr-p place) + (list 'prog1 (list 'car place) (list 'setf place (list 'cdr place))) + (let* ((method (cl-setf-do-modify place t)) + (temp (gensym "--pop--"))) + (list 'let* + (append (car method) + (list (list temp (nth 2 method)))) + (list 'prog1 + (list 'car temp) + (cl-setf-do-store (nth 1 method) (list 'cdr temp))))))) + +;;;###autoload +(defmacro remf (place tag) + "(remf PLACE TAG): remove TAG from property list PLACE. +PLACE may be a symbol, or any generalized variable allowed by `setf'. +The form returns true if TAG was found and removed, nil otherwise." + (let* ((method (cl-setf-do-modify place t)) + (tag-temp (and (not (cl-const-expr-p tag)) (gensym "--remf-tag--"))) + (val-temp (and (not (cl-simple-expr-p place)) + (gensym "--remf-place--"))) + (ttag (or tag-temp tag)) + (tval (or val-temp (nth 2 method)))) + (list 'let* + (append (car method) + (and val-temp (list (list val-temp (nth 2 method)))) + (and tag-temp (list (list tag-temp tag)))) + (list 'if (list 'eq ttag (list 'car tval)) + (list 'progn + (cl-setf-do-store (nth 1 method) (list 'cddr tval)) + t) + (list 'cl-do-remf tval ttag))))) + +;;;###autoload +(defmacro shiftf (place &rest args) + "(shiftf PLACE PLACE... VAL): shift left among PLACEs. +Example: (shiftf A B C) sets A to B, B to C, and returns the old A. +Each PLACE may be a symbol, or any generalized variable allowed by `setf'." + (if (not (memq nil (mapcar 'symbolp (butlast (cons place args))))) + (list* 'prog1 place + (let ((sets nil)) + (while args + (cl-push (list 'setq place (car args)) sets) + (setq place (cl-pop args))) + (nreverse sets))) + (let* ((places (reverse (cons place args))) + (form (cl-pop places))) + (while places + (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe))) + (setq form (list 'let* (car method) + (list 'prog1 (nth 2 method) + (cl-setf-do-store (nth 1 method) form)))))) + form))) + +;;;###autoload +(defmacro rotatef (&rest args) + "(rotatef PLACE...): rotate left among PLACEs. +Example: (rotatef A B C) sets A to B, B to C, and C to A. It returns nil. +Each PLACE may be a symbol, or any generalized variable allowed by `setf'." + (if (not (memq nil (mapcar 'symbolp args))) + (and (cdr args) + (let ((sets nil) + (first (car args))) + (while (cdr args) + (setq sets (nconc sets (list (cl-pop args) (car args))))) + (nconc (list 'psetf) sets (list (car args) first)))) + (let* ((places (reverse args)) + (temp (gensym "--rotatef--")) + (form temp)) + (while (cdr places) + (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe))) + (setq form (list 'let* (car method) + (list 'prog1 (nth 2 method) + (cl-setf-do-store (nth 1 method) form)))))) + (let ((method (cl-setf-do-modify (car places) 'unsafe))) + (list 'let* (append (car method) (list (list temp (nth 2 method)))) + (cl-setf-do-store (nth 1 method) form) nil))))) + +;;;###autoload +(defmacro letf (bindings &rest body) + "(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. +This is the analogue of `let', but with generalized variables (in the +sense of `setf') for the PLACEs. Each PLACE is set to the corresponding +VALUE, then the BODY forms are executed. On exit, either normally or +because of a `throw' or error, the PLACEs are set back to their original +values. Note that this macro is *not* available in Common Lisp. +As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', +the PLACE is not modified before executing BODY." + (if (and (not (cdr bindings)) (cdar bindings) (symbolp (caar bindings))) + (list* 'let bindings body) + (let ((lets nil) (sets nil) + (unsets nil) (rev (reverse bindings))) + (while rev + (let* ((place (if (symbolp (caar rev)) + (list 'symbol-value (list 'quote (caar rev))) + (caar rev))) + (value (cadar rev)) + (method (cl-setf-do-modify place 'no-opt)) + (save (gensym "--letf-save--")) + (bound (and (memq (car place) '(symbol-value symbol-function)) + (gensym "--letf-bound--"))) + (temp (and (not (cl-const-expr-p value)) (cdr bindings) + (gensym "--letf-val--")))) + (setq lets (nconc (car method) + (if bound + (list (list bound + (list (if (eq (car place) + 'symbol-value) + 'boundp 'fboundp) + (nth 1 (nth 2 method)))) + (list save (list 'and bound + (nth 2 method)))) + (list (list save (nth 2 method)))) + (and temp (list (list temp value))) + lets) + body (list + (list 'unwind-protect + (cons 'progn + (if (cdr (car rev)) + (cons (cl-setf-do-store (nth 1 method) + (or temp value)) + body) + body)) + (if bound + (list 'if bound + (cl-setf-do-store (nth 1 method) save) + (list (if (eq (car place) 'symbol-value) + 'makunbound 'fmakunbound) + (nth 1 (nth 2 method)))) + (cl-setf-do-store (nth 1 method) save)))) + rev (cdr rev)))) + (list* 'let* lets body)))) + +;;;###autoload +(defmacro letf* (bindings &rest body) + "(letf* ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. +This is the analogue of `let*', but with generalized variables (in the +sense of `setf') for the PLACEs. Each PLACE is set to the corresponding +VALUE, then the BODY forms are executed. On exit, either normally or +because of a `throw' or error, the PLACEs are set back to their original +values. Note that this macro is *not* available in Common Lisp. +As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', +the PLACE is not modified before executing BODY." + (if (null bindings) + (cons 'progn body) + (setq bindings (reverse bindings)) + (while bindings + (setq body (list (list* 'letf (list (cl-pop bindings)) body)))) + (car body))) + +;;;###autoload +(defmacro callf (func place &rest args) + "(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...). +FUNC should be an unquoted function name. PLACE may be a symbol, +or any generalized variable allowed by `setf'." + (let* ((method (cl-setf-do-modify place (cons 'list args))) + (rargs (cons (nth 2 method) args))) + (list 'let* (car method) + (cl-setf-do-store (nth 1 method) + (if (symbolp func) (cons func rargs) + (list* 'funcall (list 'function func) + rargs)))))) + +;;;###autoload +(defmacro callf2 (func arg1 place &rest args) + "(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...). +Like `callf', but PLACE is the second argument of FUNC, not the first." + (if (and (cl-safe-expr-p arg1) (cl-simple-expr-p place) (symbolp func)) + (list 'setf place (list* func arg1 place args)) + (let* ((method (cl-setf-do-modify place (cons 'list args))) + (temp (and (not (cl-const-expr-p arg1)) (gensym "--arg1--"))) + (rargs (list* (or temp arg1) (nth 2 method) args))) + (list 'let* (append (and temp (list (list temp arg1))) (car method)) + (cl-setf-do-store (nth 1 method) + (if (symbolp func) (cons func rargs) + (list* 'funcall (list 'function func) + rargs))))))) + +;;;###autoload +(defmacro define-modify-macro (name arglist func &optional doc) + "(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro. +If NAME is called, it combines its PLACE argument with the other arguments +from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" + (if (memq '&key arglist) (error "&key not allowed in define-modify-macro")) + (let ((place (gensym "--place--"))) + (list 'defmacro* name (cons place arglist) doc + (list* (if (memq '&rest arglist) 'list* 'list) + '(quote callf) (list 'quote func) place + (cl-arglist-args arglist))))) + + +;;; Structures. + +;;;###autoload +(defmacro defstruct (struct &rest descs) + "(defstruct (NAME OPTIONS...) (SLOT SLOT-OPTS...)...): define a struct type. +This macro defines a new Lisp data type called NAME, which contains data +stored in SLOTs. This defines a `make-NAME' constructor, a `copy-NAME' +copier, a `NAME-p' predicate, and setf-able `NAME-SLOT' accessors." + (let* ((name (if (consp struct) (car struct) struct)) + (opts (cdr-safe struct)) + (slots nil) + (defaults nil) + (conc-name (concat (symbol-name name) "-")) + (constructor (intern (format "make-%s" name))) + (constrs nil) + (copier (intern (format "copy-%s" name))) + (predicate (intern (format "%s-p" name))) + (print-func nil) (print-auto nil) + (safety (if (cl-compiling-file) cl-optimize-safety 3)) + (include nil) + (tag (intern (format "cl-struct-%s" name))) + (tag-symbol (intern (format "cl-struct-%s-tags" name))) + (include-descs nil) + ;; XEmacs change + (include-tag-symbol nil) + (side-eff nil) + (type nil) + (named nil) + (forms nil) + pred-form pred-check) + (if (stringp (car descs)) + (cl-push (list 'put (list 'quote name) '(quote structure-documentation) + (cl-pop descs)) forms)) + (setq descs (cons '(cl-tag-slot) + (mapcar (function (lambda (x) (if (consp x) x (list x)))) + descs))) + (while opts + (let ((opt (if (consp (car opts)) (caar opts) (car opts))) + (args (cdr-safe (cl-pop opts)))) + (cond ((eq opt ':conc-name) + (if args + (setq conc-name (if (car args) + (symbol-name (car args)) "")))) + ((eq opt ':constructor) + (if (cdr args) + (cl-push args constrs) + (if args (setq constructor (car args))))) + ((eq opt ':copier) + (if args (setq copier (car args)))) + ((eq opt ':predicate) + (if args (setq predicate (car args)))) + ((eq opt ':include) + (setq include (car args) + include-descs (mapcar (function + (lambda (x) + (if (consp x) x (list x)))) + (cdr args)) + ;; XEmacs change + include-tag-symbol (intern (format "cl-struct-%s-tags" + include)))) + ((eq opt ':print-function) + (setq print-func (car args))) + ((eq opt ':type) + (setq type (car args))) + ((eq opt ':named) + (setq named t)) + ((eq opt ':initial-offset) + (setq descs (nconc (make-list (car args) '(cl-skip-slot)) + descs))) + (t + (error "Slot option %s unrecognized" opt))))) + (if print-func + (setq print-func (list 'progn + (list 'funcall (list 'function print-func) + 'cl-x 'cl-s 'cl-n) t)) + (or type (and include (not (get include 'cl-struct-print))) + (setq print-auto t + print-func (and (or (not (or include type)) (null print-func)) + (list 'progn + (list 'princ (format "#S(%s" name) + 'cl-s)))))) + (if include + (let ((inc-type (get include 'cl-struct-type)) + (old-descs (get include 'cl-struct-slots))) + (or inc-type (error "%s is not a struct name" include)) + (and type (not (eq (car inc-type) type)) + (error ":type disagrees with :include for %s" name)) + (while include-descs + (setcar (memq (or (assq (caar include-descs) old-descs) + (error "No slot %s in included struct %s" + (caar include-descs) include)) + old-descs) + (cl-pop include-descs))) + (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs)) + type (car inc-type) + named (assq 'cl-tag-slot descs)) + (if (cadr inc-type) (setq tag name named t)) + (let ((incl include)) + (while incl + (cl-push (list 'pushnew (list 'quote tag) + (intern (format "cl-struct-%s-tags" incl))) + forms) + (setq incl (get incl 'cl-struct-include))))) + (if type + (progn + (or (memq type '(vector list)) + (error "Illegal :type specifier: %s" type)) + (if named (setq tag name))) + (setq type 'vector named 'true))) + (or named (setq descs (delq (assq 'cl-tag-slot descs) descs))) + (cl-push (list 'defvar tag-symbol) forms) + (setq pred-form (and named + (let ((pos (- (length descs) + (length (memq (assq 'cl-tag-slot descs) + descs))))) + (if (eq type 'vector) + (list 'and '(vectorp cl-x) + (list '>= '(length cl-x) (length descs)) + (list 'memq (list 'aref 'cl-x pos) + tag-symbol)) + (if (= pos 0) + (list 'memq '(car-safe cl-x) tag-symbol) + (list 'and '(consp cl-x) + (list 'memq (list 'nth pos 'cl-x) + tag-symbol)))))) + pred-check (and pred-form (> safety 0) + (if (and (eq (caadr pred-form) 'vectorp) + (= safety 1)) + (cons 'and (cdddr pred-form)) pred-form))) + (let ((pos 0) (descp descs)) + (while descp + (let* ((desc (cl-pop descp)) + (slot (car desc))) + (if (memq slot '(cl-tag-slot cl-skip-slot)) + (progn + (cl-push nil slots) + (cl-push (and (eq slot 'cl-tag-slot) (list 'quote tag)) + defaults)) + (if (assq slot descp) + (error "Duplicate slots named %s in %s" slot name)) + (let ((accessor (intern (format "%s%s" conc-name slot)))) + (cl-push slot slots) + (cl-push (nth 1 desc) defaults) + (cl-push (list* + 'defsubst* accessor '(cl-x) + (append + (and pred-check + (list (list 'or pred-check + (list 'error + (format "%s accessing a non-%s" + accessor name) + 'cl-x)))) + (list (if (eq type 'vector) (list 'aref 'cl-x pos) + (if (= pos 0) '(car cl-x) + (list 'nth pos 'cl-x)))))) forms) + (cl-push (cons accessor t) side-eff) + (cl-push (list 'define-setf-method accessor '(cl-x) + (if (cadr (memq ':read-only (cddr desc))) + (list 'error (format "%s is a read-only slot" + accessor)) + (list 'cl-struct-setf-expander 'cl-x + (list 'quote name) (list 'quote accessor) + (and pred-check (list 'quote pred-check)) + pos))) + forms) + (if print-auto + (nconc print-func + (list (list 'princ (format " %s" slot) 'cl-s) + (list 'prin1 (list accessor 'cl-x) 'cl-s))))))) + (setq pos (1+ pos)))) + (setq slots (nreverse slots) + defaults (nreverse defaults)) + (and predicate pred-form + (progn (cl-push (list 'defsubst* predicate '(cl-x) + (if (eq (car pred-form) 'and) + (append pred-form '(t)) + (list 'and pred-form t))) forms) + (cl-push (cons predicate 'error-free) side-eff))) + (and copier + (progn (cl-push (list 'defun copier '(x) '(copy-sequence x)) forms) + (cl-push (cons copier t) side-eff))) + (if constructor + (cl-push (list constructor + (cons '&key (delq nil (copy-sequence slots)))) + constrs)) + (while constrs + (let* ((name (caar constrs)) + (args (cadr (cl-pop constrs))) + (anames (cl-arglist-args args)) + (make (mapcar* (function (lambda (s d) (if (memq s anames) s d))) + slots defaults))) + (cl-push (list 'defsubst* name + (list* '&cl-defs (list 'quote (cons nil descs)) args) + (cons type make)) forms) + (if (cl-safe-expr-p (cons 'progn (mapcar 'second descs))) + (cl-push (cons name t) side-eff)))) + (if print-auto (nconc print-func (list '(princ ")" cl-s) t))) + (if print-func + (cl-push (list 'push + (list 'function + (list 'lambda '(cl-x cl-s cl-n) + (list 'and pred-form print-func))) + 'custom-print-functions) forms)) + (cl-push (list 'setq tag-symbol (list 'list (list 'quote tag))) forms) + (cl-push (list* 'eval-when '(compile load eval) + (list 'put (list 'quote name) '(quote cl-struct-slots) + (list 'quote descs)) + (list 'put (list 'quote name) '(quote cl-struct-type) + (list 'quote (list type (eq named t)))) + (list 'put (list 'quote name) '(quote cl-struct-include) + (list 'quote include)) + (list 'put (list 'quote name) '(quote cl-struct-print) + print-auto) + (mapcar (function (lambda (x) + (list 'put (list 'quote (car x)) + '(quote side-effect-free) + (list 'quote (cdr x))))) + side-eff)) + forms) + (cons 'progn (nreverse (cons (list 'quote name) forms))))) + +;;;###autoload +(defun cl-struct-setf-expander (x name accessor pred-form pos) + (let* ((temp (gensym "--x--")) (store (gensym "--store--"))) + (list (list temp) (list x) (list store) + (append '(progn) + (and pred-form + (list (list 'or (subst temp 'cl-x pred-form) + (list 'error + (format + "%s storing a non-%s" accessor name) + temp)))) + (list (if (eq (car (get name 'cl-struct-type)) 'vector) + (list 'aset temp pos store) + (list 'setcar + (if (<= pos 5) + (let ((xx temp)) + (while (>= (setq pos (1- pos)) 0) + (setq xx (list 'cdr xx))) + xx) + (list 'nthcdr pos temp)) + store)))) + (list accessor temp)))) + + +;;; Types and assertions. + +;;;###autoload +(defmacro deftype (name args &rest body) + "(deftype NAME ARGLIST BODY...): define NAME as a new data type. +The type name can then be used in `typecase', `check-type', etc." + (list 'eval-when '(compile load eval) + (cl-transform-function-property + name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) args) body)))) + +(defun cl-make-type-test (val type) + (if (symbolp type) + (cond ((get type 'cl-deftype-handler) + (cl-make-type-test val (funcall (get type 'cl-deftype-handler)))) + ((memq type '(nil t)) type) + ((eq type 'string-char) (list 'characterp val)) + ((eq type 'null) (list 'null val)) + ((eq type 'float) (list 'floatp-safe val)) + ((eq type 'real) (list 'numberp val)) + ((eq type 'fixnum) (list 'integerp val)) + (t + (let* ((name (symbol-name type)) + (namep (intern (concat name "p")))) + (if (fboundp namep) (list namep val) + (list (intern (concat name "-p")) val))))) + (cond ((get (car type) 'cl-deftype-handler) + (cl-make-type-test val (apply (get (car type) 'cl-deftype-handler) + (cdr type)))) + ((memq (car-safe type) '(integer float real number)) + (delq t (list 'and (cl-make-type-test val (car type)) + (if (memq (cadr type) '(* nil)) t + (if (consp (cadr type)) (list '> val (caadr type)) + (list '>= val (cadr type)))) + (if (memq (caddr type) '(* nil)) t + (if (consp (caddr type)) (list '< val (caaddr type)) + (list '<= val (caddr type))))))) + ((memq (car-safe type) '(and or not)) + (cons (car type) + (mapcar (function (lambda (x) (cl-make-type-test val x))) + (cdr type)))) + ((memq (car-safe type) '(member member*)) + (list 'and (list 'member* val (list 'quote (cdr type))) t)) + ((eq (car-safe type) 'satisfies) (list (cadr type) val)) + (t (error "Bad type spec: %s" type))))) + +;;;###autoload +(defun typep (val type) ; See compiler macro below. + "Check that OBJECT is of type TYPE. +TYPE is a Common Lisp-style type specifier." + (eval (cl-make-type-test 'val type))) + +;;;###autoload +(defmacro check-type (form type &optional string) + "Verify that FORM is of type TYPE; signal an error if not. +STRING is an optional description of the desired type." + (and (or (not (cl-compiling-file)) + (< cl-optimize-speed 3) (= cl-optimize-safety 3)) + (let* ((temp (if (cl-simple-expr-p form 3) form (gensym))) + (body (list 'or (cl-make-type-test temp type) + (list 'signal '(quote wrong-type-argument) + (list 'list (or string (list 'quote type)) + temp (list 'quote form)))))) + (if (eq temp form) (list 'progn body nil) + (list 'let (list (list temp form)) body nil))))) + +;;;###autoload +(defmacro assert (form &optional show-args string &rest args) + "Verify that FORM returns non-nil; signal an error if not. +Second arg SHOW-ARGS means to include arguments of FORM in message. +Other args STRING and ARGS... are arguments to be passed to `error'. +They are not evaluated unless the assertion fails. If STRING is +omitted, a default message listing FORM itself is used." + (and (or (not (cl-compiling-file)) + (< cl-optimize-speed 3) (= cl-optimize-safety 3)) + (let ((sargs (and show-args (delq nil (mapcar + (function + (lambda (x) + (and (not (cl-const-expr-p x)) + x))) (cdr form)))))) + (list 'progn + (list 'or form + (if string + (list* 'error string (append sargs args)) + (list 'signal '(quote cl-assertion-failed) + (list* 'list (list 'quote form) sargs)))) + nil)))) + +;;;###autoload +(defmacro ignore-errors (&rest body) + "Execute FORMS; if an error occurs, return nil. +Otherwise, return result of last FORM." + (list 'condition-case nil (cons 'progn body) '(error nil))) + + +;;; Some predicates for analyzing Lisp forms. These are used by various +;;; macro expanders to optimize the results in certain common cases. + +(defconst cl-simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max + car-safe cdr-safe progn prog1 prog2)) +(defconst cl-safe-funcs '(* / % length memq list vector vectorp + < > <= >= = error)) + +;;; Check if no side effects, and executes quickly. +(defun cl-simple-expr-p (x &optional size) + (or size (setq size 10)) + (if (and (consp x) (not (memq (car x) '(quote function function*)))) + (and (symbolp (car x)) + (or (memq (car x) cl-simple-funcs) + (get (car x) 'side-effect-free)) + (progn + (setq size (1- size)) + (while (and (setq x (cdr x)) + (setq size (cl-simple-expr-p (car x) size)))) + (and (null x) (>= size 0) size))) + (and (> size 0) (1- size)))) + +(defun cl-simple-exprs-p (xs) + (while (and xs (cl-simple-expr-p (car xs))) + (setq xs (cdr xs))) + (not xs)) + +;;; Check if no side effects. +(defun cl-safe-expr-p (x) + (or (not (and (consp x) (not (memq (car x) '(quote function function*))))) + (and (symbolp (car x)) + (or (memq (car x) cl-simple-funcs) + (memq (car x) cl-safe-funcs) + (get (car x) 'side-effect-free)) + (progn + (while (and (setq x (cdr x)) (cl-safe-expr-p (car x)))) + (null x))))) + +;;; Check if constant (i.e., no side effects or dependencies). +(defun cl-const-expr-p (x) + (cond ((consp x) + (or (eq (car x) 'quote) + (and (memq (car x) '(function function*)) + (or (symbolp (nth 1 x)) + (and (eq (car-safe (nth 1 x)) 'lambda) 'func))))) + ((symbolp x) (and (memq x '(nil t)) t)) + (t t))) + +(defun cl-const-exprs-p (xs) + (while (and xs (cl-const-expr-p (car xs))) + (setq xs (cdr xs))) + (not xs)) + +(defun cl-const-expr-val (x) + (and (eq (cl-const-expr-p x) t) (if (consp x) (nth 1 x) x))) + +(defun cl-expr-access-order (x v) + (if (cl-const-expr-p x) v + (if (consp x) + (progn + (while (setq x (cdr x)) (setq v (cl-expr-access-order (car x) v))) + v) + (if (eq x (car v)) (cdr v) '(t))))) + +;;; Count number of times X refers to Y. Return NIL for 0 times. +(defun cl-expr-contains (x y) + (cond ((equal y x) 1) + ((and (consp x) (not (memq (car-safe x) '(quote function function*)))) + (let ((sum 0)) + (while x + (setq sum (+ sum (or (cl-expr-contains (cl-pop x) y) 0)))) + (and (> sum 0) sum))) + (t nil))) + +(defun cl-expr-contains-any (x y) + (while (and y (not (cl-expr-contains x (car y)))) (cl-pop y)) + y) + +;;; Check whether X may depend on any of the symbols in Y. +(defun cl-expr-depends-p (x y) + (and (not (cl-const-expr-p x)) + (or (not (cl-safe-expr-p x)) (cl-expr-contains-any x y)))) + + +;;; Compiler macros. + +;;;###autoload +(defmacro define-compiler-macro (func args &rest body) + "(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro. +This is like `defmacro', but macro expansion occurs only if the call to +FUNC is compiled (i.e., not interpreted). Compiler macros should be used +for optimizing the way calls to FUNC are compiled; the form returned by +BODY should do the same thing as a call to the normal function called +FUNC, though possibly more efficiently. Note that, like regular macros, +compiler macros are expanded repeatedly until no further expansions are +possible. Unlike regular macros, BODY can decide to \"punt\" and leave the +original function call alone by declaring an initial `&whole foo' parameter +and then returning foo." + (let ((p (if (listp args) args (list '&rest args))) (res nil)) + (while (consp p) (cl-push (cl-pop p) res)) + (setq args (nreverse res)) (setcdr res (and p (list '&rest p)))) + (list 'eval-when '(compile load eval) + (cl-transform-function-property + func 'cl-compiler-macro + (cons (if (memq '&whole args) (delq '&whole args) + (cons '--cl-whole-arg-- args)) body)) + (list 'or (list 'get (list 'quote func) '(quote byte-compile)) + (list 'put (list 'quote func) '(quote byte-compile) + '(quote cl-byte-compile-compiler-macro))))) + +;;;###autoload +(defun compiler-macroexpand (form) + (while + (let ((func (car-safe form)) (handler nil)) + (while (and (symbolp func) + (not (setq handler (get func 'cl-compiler-macro))) + (fboundp func) + (or (not (eq (car-safe (symbol-function func)) 'autoload)) + (load (nth 1 (symbol-function func))))) + (setq func (symbol-function func))) + (and handler + (not (eq form (setq form (apply handler form (cdr form)))))))) + form) + +(defun cl-byte-compile-compiler-macro (form) + (if (eq form (setq form (compiler-macroexpand form))) + (byte-compile-normal-call form) + (byte-compile-form form))) + +(defmacro defsubst* (name args &rest body) + "(defsubst* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. +Like `defun', except the function is automatically declared `inline', +ARGLIST allows full Common Lisp conventions, and BODY is implicitly +surrounded by (block NAME ...)." + (let* ((argns (cl-arglist-args args)) (p argns) + (pbody (cons 'progn body)) + (unsafe (not (cl-safe-expr-p pbody)))) + (while (and p (eq (cl-expr-contains args (car p)) 1)) (cl-pop p)) + (list 'progn + (if p nil ; give up if defaults refer to earlier args + (list 'define-compiler-macro name + (list* '&whole 'cl-whole '&cl-quote args) + (list* 'cl-defsubst-expand (list 'quote argns) + (list 'quote (list* 'block name body)) + (not (or unsafe (cl-expr-access-order pbody argns))) + (and (memq '&key args) 'cl-whole) unsafe argns))) + (list* 'defun* name args body)))) + +(defun cl-defsubst-expand (argns body simple whole unsafe &rest argvs) + (if (and whole (not (cl-safe-expr-p (cons 'progn argvs)))) whole + (if (cl-simple-exprs-p argvs) (setq simple t)) + (let ((lets (delq nil + (mapcar* (function + (lambda (argn argv) + (if (or simple (cl-const-expr-p argv)) + (progn (setq body (subst argv argn body)) + (and unsafe (list argn argv))) + (list argn argv)))) + argns argvs)))) + (if lets (list 'let lets body) body)))) + + +;;; Compile-time optimizations for some functions defined in this package. +;;; Note that cl.el arranges to force cl-macs to be loaded at compile-time, +;;; mainly to make sure these macros will be present. + +(put 'eql 'byte-compile nil) +(define-compiler-macro eql (&whole form a b) + (cond ((eq (cl-const-expr-p a) t) + (let ((val (cl-const-expr-val a))) + (if (and (numberp val) (not (integerp val))) + (list 'equal a b) + (list 'eq a b)))) + ((eq (cl-const-expr-p b) t) + (let ((val (cl-const-expr-val b))) + (if (and (numberp val) (not (integerp val))) + (list 'equal a b) + (list 'eq a b)))) + ((cl-simple-expr-p a 5) + (list 'if (list 'numberp a) + (list 'equal a b) + (list 'eq a b))) + ((and (cl-safe-expr-p a) + (cl-simple-expr-p b 5)) + (list 'if (list 'numberp b) + (list 'equal a b) + (list 'eq a b))) + (t form))) + +(define-compiler-macro member* (&whole form a list &rest keys) + (let ((test (and (= (length keys) 2) (eq (car keys) ':test) + (cl-const-expr-val (nth 1 keys))))) + (cond ((eq test 'eq) (list 'memq a list)) + ((eq test 'equal) (list 'member a list)) + ((or (null keys) (eq test 'eql)) + (if (eq (cl-const-expr-p a) t) + (list (if (floatp-safe (cl-const-expr-val a)) 'member 'memq) + a list) + (if (eq (cl-const-expr-p list) t) + (let ((p (cl-const-expr-val list)) (mb nil) (mq nil)) + (if (not (cdr p)) + (and p (list 'eql a (list 'quote (car p)))) + (while p + (if (floatp-safe (car p)) (setq mb t) + (or (integerp (car p)) (symbolp (car p)) (setq mq t))) + (setq p (cdr p))) + (if (not mb) (list 'memq a list) + (if (not mq) (list 'member a list) form)))) + form))) + (t form)))) + +(define-compiler-macro assoc* (&whole form a list &rest keys) + (let ((test (and (= (length keys) 2) (eq (car keys) ':test) + (cl-const-expr-val (nth 1 keys))))) + (cond ((eq test 'eq) (list 'assq a list)) + ((eq test 'equal) (list 'assoc a list)) + ((and (eq (cl-const-expr-p a) t) (or (null keys) (eq test 'eql))) + (if (floatp-safe (cl-const-expr-val a)) + (list 'assoc a list) (list 'assq a list))) + (t form)))) + +(define-compiler-macro adjoin (&whole form a list &rest keys) + (if (and (cl-simple-expr-p a) (cl-simple-expr-p list) + (not (memq ':key keys))) + (list 'if (list* 'member* a list keys) list (list 'cons a list)) + form)) + +(define-compiler-macro list* (arg &rest others) + (let* ((args (reverse (cons arg others))) + (form (car args))) + (while (setq args (cdr args)) + (setq form (list 'cons (car args) form))) + form)) + +(define-compiler-macro get* (sym prop &optional def) + (if def + (list 'getf (list 'symbol-plist sym) prop def) + (list 'get sym prop))) + +(define-compiler-macro typep (&whole form val type) + (if (cl-const-expr-p type) + (let ((res (cl-make-type-test val (cl-const-expr-val type)))) + (if (or (memq (cl-expr-contains res val) '(nil 1)) + (cl-simple-expr-p val)) res + (let ((temp (gensym))) + (list 'let (list (list temp val)) (subst temp val res))))) + form)) + + +(mapcar (function + (lambda (y) + (put (car y) 'side-effect-free t) + (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro) + (put (car y) 'cl-compiler-macro + (list 'lambda '(w x) + (if (symbolp (cadr y)) + (list 'list (list 'quote (cadr y)) + (list 'list (list 'quote (caddr y)) 'x)) + (cons 'list (cdr y))))))) + '((first 'car x) (second 'cadr x) (third 'caddr x) (fourth 'cadddr x) + (fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x) + (eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x) + (rest 'cdr x) (endp 'null x) (plusp '> x 0) (minusp '< x 0) + (caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr) + (caaar car caar) (caadr car cadr) (cadar car cdar) + (caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr) + (cddar cdr cdar) (cdddr cdr cddr) (caaaar car caaar) + (caaadr car caadr) (caadar car cadar) (caaddr car caddr) + (cadaar car cdaar) (cadadr car cdadr) (caddar car cddar) + (cadddr car cdddr) (cdaaar cdr caaar) (cdaadr cdr caadr) + (cdadar cdr cadar) (cdaddr cdr caddr) (cddaar cdr cdaar) + (cddadr cdr cdadr) (cdddar cdr cddar) (cddddr cdr cdddr) )) + +;;; Things that are inline. +(proclaim '(inline floatp-safe acons map concatenate notany notevery +;; XEmacs change + cl-set-elt revappend nreconc)) + +;;; Things that are side-effect-free. +(mapcar (function (lambda (x) (put x 'side-effect-free t))) + '(oddp evenp abs expt signum last butlast ldiff pairlis gcd lcm + isqrt floor* ceiling* truncate* round* mod* rem* subseq + list-length get* getf gethash hash-table-count)) + +;;; Things that are side-effect-and-error-free. +(mapcar (function (lambda (x) (put x 'side-effect-free 'error-free))) + '(eql floatp-safe list* subst acons equalp random-state-p + copy-tree sublis hash-table-p)) + + +(run-hooks 'cl-macs-load-hook) + +;;; cl-macs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl-seq.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cl-seq.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,938 @@ +;;; cl-seq.el --- Common Lisp extensions for GNU Emacs Lisp (part three) + +;; Copyright (C) 1993 Free Software Foundation, Inc. + +;; Author: Dave Gillespie +;; Maintainer: XEmacs Development Team +;; Version: 2.02 +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; These are extensions to Emacs Lisp that provide a degree of +;; Common Lisp compatibility, beyond what is already built-in +;; in Emacs Lisp. +;; +;; This package was written by Dave Gillespie; it is a complete +;; rewrite of Cesar Quiroz's original cl.el package of December 1986. +;; +;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. +;; +;; Bug reports, comments, and suggestions are welcome! + +;; This file contains the Common Lisp sequence and list functions +;; which take keyword arguments. + +;; See cl.el for Change Log. + + +;;; Code: + +(or (memq 'cl-19 features) + (error "Tried to load `cl-seq' before `cl'!")) + + +;;; We define these here so that this file can compile without having +;;; loaded the cl.el file already. + +(defmacro cl-push (x place) (list 'setq place (list 'cons x place))) +(defmacro cl-pop (place) + (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) + + +;;; Keyword parsing. This is special-cased here so that we can compile +;;; this file independent from cl-macs. + +(defmacro cl-parsing-keywords (kwords other-keys &rest body) + (cons + 'let* + (cons (mapcar + (function + (lambda (x) + (let* ((var (if (consp x) (car x) x)) + (mem (list 'car (list 'cdr (list 'memq (list 'quote var) + 'cl-keys))))) + (if (eq var ':test-not) + (setq mem (list 'and mem (list 'setq 'cl-test mem) t))) + (if (eq var ':if-not) + (setq mem (list 'and mem (list 'setq 'cl-if mem) t))) + (list (intern + (format "cl-%s" (substring (symbol-name var) 1))) + (if (consp x) (list 'or mem (car (cdr x))) mem))))) + kwords) + (append + (and (not (eq other-keys t)) + (list + (list 'let '((cl-keys-temp cl-keys)) + (list 'while 'cl-keys-temp + (list 'or (list 'memq '(car cl-keys-temp) + (list 'quote + (mapcar + (function + (lambda (x) + (if (consp x) + (car x) x))) + (append kwords + other-keys)))) + '(car (cdr (memq (quote :allow-other-keys) + cl-keys))) + '(error "Bad keyword argument %s" + (car cl-keys-temp))) + '(setq cl-keys-temp (cdr (cdr cl-keys-temp))))))) + body)))) +(put 'cl-parsing-keywords 'lisp-indent-function 2) +(put 'cl-parsing-keywords 'edebug-form-spec '(sexp sexp &rest form)) + +(defmacro cl-check-key (x) + (list 'if 'cl-key (list 'funcall 'cl-key x) x)) + +(defmacro cl-check-test-nokey (item x) + (list 'cond + (list 'cl-test + (list 'eq (list 'not (list 'funcall 'cl-test item x)) + 'cl-test-not)) + (list 'cl-if + (list 'eq (list 'not (list 'funcall 'cl-if x)) 'cl-if-not)) + (list 't (list 'if (list 'numberp item) + (list 'equal item x) (list 'eq item x))))) + +(defmacro cl-check-test (item x) + (list 'cl-check-test-nokey item (list 'cl-check-key x))) + +(defmacro cl-check-match (x y) + (setq x (list 'cl-check-key x) y (list 'cl-check-key y)) + (list 'if 'cl-test + (list 'eq (list 'not (list 'funcall 'cl-test x y)) 'cl-test-not) + (list 'if (list 'numberp x) + (list 'equal x y) (list 'eq x y)))) + +(put 'cl-check-key 'edebug-form-spec 'edebug-forms) +(put 'cl-check-test 'edebug-form-spec 'edebug-forms) +(put 'cl-check-test-nokey 'edebug-form-spec 'edebug-forms) +(put 'cl-check-match 'edebug-form-spec 'edebug-forms) + +(defvar cl-test) (defvar cl-test-not) +(defvar cl-if) (defvar cl-if-not) +(defvar cl-key) + + +(defun reduce (cl-func cl-seq &rest cl-keys) + "Reduce two-argument FUNCTION across SEQUENCE. +Keywords supported: :start :end :from-end :initial-value :key" + (cl-parsing-keywords (:from-end (:start 0) :end :initial-value :key) () + (or (listp cl-seq) (setq cl-seq (append cl-seq nil))) + (setq cl-seq (subseq cl-seq cl-start cl-end)) + (if cl-from-end (setq cl-seq (nreverse cl-seq))) + (let ((cl-accum (cond ((memq ':initial-value cl-keys) cl-initial-value) + (cl-seq (cl-check-key (cl-pop cl-seq))) + (t (funcall cl-func))))) + (if cl-from-end + (while cl-seq + (setq cl-accum (funcall cl-func (cl-check-key (cl-pop cl-seq)) + cl-accum))) + (while cl-seq + (setq cl-accum (funcall cl-func cl-accum + (cl-check-key (cl-pop cl-seq)))))) + cl-accum))) + +(defun fill (seq item &rest cl-keys) + "Fill the elements of SEQ with ITEM. +Keywords supported: :start :end" + (cl-parsing-keywords ((:start 0) :end) () + (if (listp seq) + (let ((p (nthcdr cl-start seq)) + (n (if cl-end (- cl-end cl-start) 8000000))) + (while (and p (>= (setq n (1- n)) 0)) + (setcar p item) + (setq p (cdr p)))) + (or cl-end (setq cl-end (length seq))) + (if (and (= cl-start 0) (= cl-end (length seq))) + (fillarray seq item) + (while (< cl-start cl-end) + (aset seq cl-start item) + (setq cl-start (1+ cl-start))))) + seq)) + +(defun replace (cl-seq1 cl-seq2 &rest cl-keys) + "Replace the elements of SEQ1 with the elements of SEQ2. +SEQ1 is destructively modified, then returned. +Keywords supported: :start1 :end1 :start2 :end2" + (cl-parsing-keywords ((:start1 0) :end1 (:start2 0) :end2) () + (if (and (eq cl-seq1 cl-seq2) (<= cl-start2 cl-start1)) + (or (= cl-start1 cl-start2) + (let* ((cl-len (length cl-seq1)) + (cl-n (min (- (or cl-end1 cl-len) cl-start1) + (- (or cl-end2 cl-len) cl-start2)))) + (while (>= (setq cl-n (1- cl-n)) 0) + (cl-set-elt cl-seq1 (+ cl-start1 cl-n) + (elt cl-seq2 (+ cl-start2 cl-n)))))) + (if (listp cl-seq1) + (let ((cl-p1 (nthcdr cl-start1 cl-seq1)) + (cl-n1 (if cl-end1 (- cl-end1 cl-start1) 4000000))) + (if (listp cl-seq2) + (let ((cl-p2 (nthcdr cl-start2 cl-seq2)) + (cl-n (min cl-n1 + (if cl-end2 (- cl-end2 cl-start2) 4000000)))) + (while (and cl-p1 cl-p2 (>= (setq cl-n (1- cl-n)) 0)) + (setcar cl-p1 (car cl-p2)) + (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))) + (setq cl-end2 (min (or cl-end2 (length cl-seq2)) + (+ cl-start2 cl-n1))) + (while (and cl-p1 (< cl-start2 cl-end2)) + (setcar cl-p1 (aref cl-seq2 cl-start2)) + (setq cl-p1 (cdr cl-p1) cl-start2 (1+ cl-start2))))) + (setq cl-end1 (min (or cl-end1 (length cl-seq1)) + (+ cl-start1 (- (or cl-end2 (length cl-seq2)) + cl-start2)))) + (if (listp cl-seq2) + (let ((cl-p2 (nthcdr cl-start2 cl-seq2))) + (while (< cl-start1 cl-end1) + (aset cl-seq1 cl-start1 (car cl-p2)) + (setq cl-p2 (cdr cl-p2) cl-start1 (1+ cl-start1)))) + (while (< cl-start1 cl-end1) + (aset cl-seq1 cl-start1 (aref cl-seq2 cl-start2)) + (setq cl-start2 (1+ cl-start2) cl-start1 (1+ cl-start1)))))) + cl-seq1)) + +(defun remove* (cl-item cl-seq &rest cl-keys) + "Remove all occurrences of ITEM in SEQ. +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Keywords supported: :test :test-not :key :count :start :end :from-end" + (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end + (:start 0) :end) () + (if (<= (or cl-count (setq cl-count 8000000)) 0) + cl-seq + (if (or (nlistp cl-seq) (and cl-from-end (< cl-count 4000000))) + (let ((cl-i (cl-position cl-item cl-seq cl-start cl-end + cl-from-end))) + (if cl-i + (let ((cl-res (apply 'delete* cl-item (append cl-seq nil) + (append (if cl-from-end + (list ':end (1+ cl-i)) + (list ':start cl-i)) + cl-keys)))) + (if (listp cl-seq) cl-res + (if (stringp cl-seq) (concat cl-res) (vconcat cl-res)))) + cl-seq)) + (setq cl-end (- (or cl-end 8000000) cl-start)) + (if (= cl-start 0) + (while (and cl-seq (> cl-end 0) + (cl-check-test cl-item (car cl-seq)) + (setq cl-end (1- cl-end) cl-seq (cdr cl-seq)) + (> (setq cl-count (1- cl-count)) 0)))) + (if (and (> cl-count 0) (> cl-end 0)) + (let ((cl-p (if (> cl-start 0) (nthcdr cl-start cl-seq) + (setq cl-end (1- cl-end)) (cdr cl-seq)))) + (while (and cl-p (> cl-end 0) + (not (cl-check-test cl-item (car cl-p)))) + (setq cl-p (cdr cl-p) cl-end (1- cl-end))) + (if (and cl-p (> cl-end 0)) + (nconc (ldiff cl-seq cl-p) + (if (= cl-count 1) (cdr cl-p) + (and (cdr cl-p) + (apply 'delete* cl-item + (copy-sequence (cdr cl-p)) + ':start 0 ':end (1- cl-end) + ':count (1- cl-count) cl-keys)))) + cl-seq)) + cl-seq))))) + +(defun remove-if (cl-pred cl-list &rest cl-keys) + "Remove all items satisfying PREDICATE in SEQ. +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Keywords supported: :key :count :start :end :from-end" + (apply 'remove* nil cl-list ':if cl-pred cl-keys)) + +(defun remove-if-not (cl-pred cl-list &rest cl-keys) + "Remove all items not satisfying PREDICATE in SEQ. +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Keywords supported: :key :count :start :end :from-end" + (apply 'remove* nil cl-list ':if-not cl-pred cl-keys)) + +(defun delete* (cl-item cl-seq &rest cl-keys) + "Remove all occurrences of ITEM in SEQ. +This is a destructive function; it reuses the storage of SEQ whenever possible. +Keywords supported: :test :test-not :key :count :start :end :from-end" + (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end + (:start 0) :end) () + (if (<= (or cl-count (setq cl-count 8000000)) 0) + cl-seq + (if (listp cl-seq) + (if (and cl-from-end (< cl-count 4000000)) + (let (cl-i) + (while (and (>= (setq cl-count (1- cl-count)) 0) + (setq cl-i (cl-position cl-item cl-seq cl-start + cl-end cl-from-end))) + (if (= cl-i 0) (setq cl-seq (cdr cl-seq)) + (let ((cl-tail (nthcdr (1- cl-i) cl-seq))) + (setcdr cl-tail (cdr (cdr cl-tail))))) + (setq cl-end cl-i)) + cl-seq) + (setq cl-end (- (or cl-end 8000000) cl-start)) + (if (= cl-start 0) + (progn + (while (and cl-seq + (> cl-end 0) + (cl-check-test cl-item (car cl-seq)) + (setq cl-end (1- cl-end) cl-seq (cdr cl-seq)) + (> (setq cl-count (1- cl-count)) 0))) + (setq cl-end (1- cl-end))) + (setq cl-start (1- cl-start))) + (if (and (> cl-count 0) (> cl-end 0)) + (let ((cl-p (nthcdr cl-start cl-seq))) + (while (and (cdr cl-p) (> cl-end 0)) + (if (cl-check-test cl-item (car (cdr cl-p))) + (progn + (setcdr cl-p (cdr (cdr cl-p))) + (if (= (setq cl-count (1- cl-count)) 0) + (setq cl-end 1))) + (setq cl-p (cdr cl-p))) + (setq cl-end (1- cl-end))))) + cl-seq) + (apply 'remove* cl-item cl-seq cl-keys))))) + +(defun delete-if (cl-pred cl-list &rest cl-keys) + "Remove all items satisfying PREDICATE in SEQ. +This is a destructive function; it reuses the storage of SEQ whenever possible. +Keywords supported: :key :count :start :end :from-end" + (apply 'delete* nil cl-list ':if cl-pred cl-keys)) + +(defun delete-if-not (cl-pred cl-list &rest cl-keys) + "Remove all items not satisfying PREDICATE in SEQ. +This is a destructive function; it reuses the storage of SEQ whenever possible. +Keywords supported: :key :count :start :end :from-end" + (apply 'delete* nil cl-list ':if-not cl-pred cl-keys)) + +(or (and (fboundp 'delete) (subrp (symbol-function 'delete))) + (defalias 'delete (function (lambda (x y) (delete* x y ':test 'equal))))) + +(defun remove (cl-item cl-seq) + "Remove all occurrences of ITEM in SEQ, testing with `equal' +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Also see: `remove*', `delete', `delete*'" + (remove* cl-item cl-seq ':test 'equal)) + +(defun remq (cl-elt cl-list) + "Remove all occurances of ELT in LIST, comparing with `eq'. +This is a non-destructive function; it makes a copy of LIST to avoid +corrupting the original LIST. +Also see: `delq', `delete', `delete*', `remove', `remove*'." + (if (memq cl-elt cl-list) + (delq cl-elt (copy-list cl-list)) + cl-list)) + +(defun remove-duplicates (cl-seq &rest cl-keys) + "Return a copy of SEQ with all duplicate elements removed. +Keywords supported: :test :test-not :key :start :end :from-end" + (cl-delete-duplicates cl-seq cl-keys t)) + +(defun delete-duplicates (cl-seq &rest cl-keys) + "Remove all duplicate elements from SEQ (destructively). +Keywords supported: :test :test-not :key :start :end :from-end" + (cl-delete-duplicates cl-seq cl-keys nil)) + +(defun cl-delete-duplicates (cl-seq cl-keys cl-copy) + (if (listp cl-seq) + (cl-parsing-keywords (:test :test-not :key (:start 0) :end :from-end :if) + () + (if cl-from-end + (let ((cl-p (nthcdr cl-start cl-seq)) cl-i) + (setq cl-end (- (or cl-end (length cl-seq)) cl-start)) + (while (> cl-end 1) + (setq cl-i 0) + (while (setq cl-i (cl-position (cl-check-key (car cl-p)) + (cdr cl-p) cl-i (1- cl-end))) + (if cl-copy (setq cl-seq (copy-sequence cl-seq) + cl-p (nthcdr cl-start cl-seq) cl-copy nil)) + (let ((cl-tail (nthcdr cl-i cl-p))) + (setcdr cl-tail (cdr (cdr cl-tail)))) + (setq cl-end (1- cl-end))) + (setq cl-p (cdr cl-p) cl-end (1- cl-end) + cl-start (1+ cl-start))) + cl-seq) + (setq cl-end (- (or cl-end (length cl-seq)) cl-start)) + (while (and (cdr cl-seq) (= cl-start 0) (> cl-end 1) + (cl-position (cl-check-key (car cl-seq)) + (cdr cl-seq) 0 (1- cl-end))) + (setq cl-seq (cdr cl-seq) cl-end (1- cl-end))) + (let ((cl-p (if (> cl-start 0) (nthcdr (1- cl-start) cl-seq) + (setq cl-end (1- cl-end) cl-start 1) cl-seq))) + (while (and (cdr (cdr cl-p)) (> cl-end 1)) + (if (cl-position (cl-check-key (car (cdr cl-p))) + (cdr (cdr cl-p)) 0 (1- cl-end)) + (progn + (if cl-copy (setq cl-seq (copy-sequence cl-seq) + cl-p (nthcdr (1- cl-start) cl-seq) + cl-copy nil)) + (setcdr cl-p (cdr (cdr cl-p)))) + (setq cl-p (cdr cl-p))) + (setq cl-end (1- cl-end) cl-start (1+ cl-start))) + cl-seq))) + (let ((cl-res (cl-delete-duplicates (append cl-seq nil) cl-keys nil))) + (if (stringp cl-seq) (concat cl-res) (vconcat cl-res))))) + +(defun substitute (cl-new cl-old cl-seq &rest cl-keys) + "Substitute NEW for OLD in SEQ. +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Keywords supported: :test :test-not :key :count :start :end :from-end" + (cl-parsing-keywords (:test :test-not :key :if :if-not :count + (:start 0) :end :from-end) () + (if (or (eq cl-old cl-new) + (<= (or cl-count (setq cl-from-end nil cl-count 8000000)) 0)) + cl-seq + (let ((cl-i (cl-position cl-old cl-seq cl-start cl-end))) + (if (not cl-i) + cl-seq + (setq cl-seq (copy-sequence cl-seq)) + (or cl-from-end + (progn (cl-set-elt cl-seq cl-i cl-new) + (setq cl-i (1+ cl-i) cl-count (1- cl-count)))) + (apply 'nsubstitute cl-new cl-old cl-seq ':count cl-count + ':start cl-i cl-keys)))))) + +(defun substitute-if (cl-new cl-pred cl-list &rest cl-keys) + "Substitute NEW for all items satisfying PREDICATE in SEQ. +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Keywords supported: :key :count :start :end :from-end" + (apply 'substitute cl-new nil cl-list ':if cl-pred cl-keys)) + +(defun substitute-if-not (cl-new cl-pred cl-list &rest cl-keys) + "Substitute NEW for all items not satisfying PREDICATE in SEQ. +This is a non-destructive function; it makes a copy of SEQ if necessary +to avoid corrupting the original SEQ. +Keywords supported: :key :count :start :end :from-end" + (apply 'substitute cl-new nil cl-list ':if-not cl-pred cl-keys)) + +(defun nsubstitute (cl-new cl-old cl-seq &rest cl-keys) + "Substitute NEW for OLD in SEQ. +This is a destructive function; it reuses the storage of SEQ whenever possible. +Keywords supported: :test :test-not :key :count :start :end :from-end" + (cl-parsing-keywords (:test :test-not :key :if :if-not :count + (:start 0) :end :from-end) () + (or (eq cl-old cl-new) (<= (or cl-count (setq cl-count 8000000)) 0) + (if (and (listp cl-seq) (or (not cl-from-end) (> cl-count 4000000))) + (let ((cl-p (nthcdr cl-start cl-seq))) + (setq cl-end (- (or cl-end 8000000) cl-start)) + (while (and cl-p (> cl-end 0) (> cl-count 0)) + (if (cl-check-test cl-old (car cl-p)) + (progn + (setcar cl-p cl-new) + (setq cl-count (1- cl-count)))) + (setq cl-p (cdr cl-p) cl-end (1- cl-end)))) + (or cl-end (setq cl-end (length cl-seq))) + (if cl-from-end + (while (and (< cl-start cl-end) (> cl-count 0)) + (setq cl-end (1- cl-end)) + (if (cl-check-test cl-old (elt cl-seq cl-end)) + (progn + (cl-set-elt cl-seq cl-end cl-new) + (setq cl-count (1- cl-count))))) + (while (and (< cl-start cl-end) (> cl-count 0)) + (if (cl-check-test cl-old (aref cl-seq cl-start)) + (progn + (aset cl-seq cl-start cl-new) + (setq cl-count (1- cl-count)))) + (setq cl-start (1+ cl-start)))))) + cl-seq)) + +(defun nsubstitute-if (cl-new cl-pred cl-list &rest cl-keys) + "Substitute NEW for all items satisfying PREDICATE in SEQ. +This is a destructive function; it reuses the storage of SEQ whenever possible. +Keywords supported: :key :count :start :end :from-end" + (apply 'nsubstitute cl-new nil cl-list ':if cl-pred cl-keys)) + +(defun nsubstitute-if-not (cl-new cl-pred cl-list &rest cl-keys) + "Substitute NEW for all items not satisfying PREDICATE in SEQ. +This is a destructive function; it reuses the storage of SEQ whenever possible. +Keywords supported: :key :count :start :end :from-end" + (apply 'nsubstitute cl-new nil cl-list ':if-not cl-pred cl-keys)) + +(defun find (cl-item cl-seq &rest cl-keys) + "Find the first occurrence of ITEM in LIST. +Return the matching ITEM, or nil if not found. +Keywords supported: :test :test-not :key :start :end :from-end" + (let ((cl-pos (apply 'position cl-item cl-seq cl-keys))) + (and cl-pos (elt cl-seq cl-pos)))) + +(defun find-if (cl-pred cl-list &rest cl-keys) + "Find the first item satisfying PREDICATE in LIST. +Return the matching ITEM, or nil if not found. +Keywords supported: :key :start :end :from-end" + (apply 'find nil cl-list ':if cl-pred cl-keys)) + +(defun find-if-not (cl-pred cl-list &rest cl-keys) + "Find the first item not satisfying PREDICATE in LIST. +Return the matching ITEM, or nil if not found. +Keywords supported: :key :start :end :from-end" + (apply 'find nil cl-list ':if-not cl-pred cl-keys)) + +(defun position (cl-item cl-seq &rest cl-keys) + "Find the first occurrence of ITEM in LIST. +Return the index of the matching item, or nil if not found. +Keywords supported: :test :test-not :key :start :end :from-end" + (cl-parsing-keywords (:test :test-not :key :if :if-not + (:start 0) :end :from-end) () + (cl-position cl-item cl-seq cl-start cl-end cl-from-end))) + +(defun cl-position (cl-item cl-seq cl-start &optional cl-end cl-from-end) + (if (listp cl-seq) + (let ((cl-p (nthcdr cl-start cl-seq))) + (or cl-end (setq cl-end 8000000)) + (let ((cl-res nil)) + (while (and cl-p (< cl-start cl-end) (or (not cl-res) cl-from-end)) + (if (cl-check-test cl-item (car cl-p)) + (setq cl-res cl-start)) + (setq cl-p (cdr cl-p) cl-start (1+ cl-start))) + cl-res)) + (or cl-end (setq cl-end (length cl-seq))) + (if cl-from-end + (progn + (while (and (>= (setq cl-end (1- cl-end)) cl-start) + (not (cl-check-test cl-item (aref cl-seq cl-end))))) + (and (>= cl-end cl-start) cl-end)) + (while (and (< cl-start cl-end) + (not (cl-check-test cl-item (aref cl-seq cl-start)))) + (setq cl-start (1+ cl-start))) + (and (< cl-start cl-end) cl-start)))) + +(defun position-if (cl-pred cl-list &rest cl-keys) + "Find the first item satisfying PREDICATE in LIST. +Return the index of the matching item, or nil if not found. +Keywords supported: :key :start :end :from-end" + (apply 'position nil cl-list ':if cl-pred cl-keys)) + +(defun position-if-not (cl-pred cl-list &rest cl-keys) + "Find the first item not satisfying PREDICATE in LIST. +Return the index of the matching item, or nil if not found. +Keywords supported: :key :start :end :from-end" + (apply 'position nil cl-list ':if-not cl-pred cl-keys)) + +(defun count (cl-item cl-seq &rest cl-keys) + "Count the number of occurrences of ITEM in LIST. +Keywords supported: :test :test-not :key :start :end" + (cl-parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end) () + (let ((cl-count 0) cl-x) + (or cl-end (setq cl-end (length cl-seq))) + (if (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq))) + (while (< cl-start cl-end) + (setq cl-x (if (consp cl-seq) (cl-pop cl-seq) (aref cl-seq cl-start))) + (if (cl-check-test cl-item cl-x) (setq cl-count (1+ cl-count))) + (setq cl-start (1+ cl-start))) + cl-count))) + +(defun count-if (cl-pred cl-list &rest cl-keys) + "Count the number of items satisfying PREDICATE in LIST. +Keywords supported: :key :start :end" + (apply 'count nil cl-list ':if cl-pred cl-keys)) + +(defun count-if-not (cl-pred cl-list &rest cl-keys) + "Count the number of items not satisfying PREDICATE in LIST. +Keywords supported: :key :start :end" + (apply 'count nil cl-list ':if-not cl-pred cl-keys)) + +(defun mismatch (cl-seq1 cl-seq2 &rest cl-keys) + "Compare SEQ1 with SEQ2, return index of first mismatching element. +Return nil if the sequences match. If one sequence is a prefix of the +other, the return value indicates the end of the shorted sequence. +Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end" + (cl-parsing-keywords (:test :test-not :key :from-end + (:start1 0) :end1 (:start2 0) :end2) () + (or cl-end1 (setq cl-end1 (length cl-seq1))) + (or cl-end2 (setq cl-end2 (length cl-seq2))) + (if cl-from-end + (progn + (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2) + (cl-check-match (elt cl-seq1 (1- cl-end1)) + (elt cl-seq2 (1- cl-end2)))) + (setq cl-end1 (1- cl-end1) cl-end2 (1- cl-end2))) + (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2)) + (1- cl-end1))) + (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1))) + (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2)))) + (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2) + (cl-check-match (if cl-p1 (car cl-p1) + (aref cl-seq1 cl-start1)) + (if cl-p2 (car cl-p2) + (aref cl-seq2 cl-start2)))) + (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2) + cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2))) + (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2)) + cl-start1))))) + +(defun search (cl-seq1 cl-seq2 &rest cl-keys) + "Search for SEQ1 as a subsequence of SEQ2. +Return the index of the leftmost element of the first match found; +return nil if there are no matches. +Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end" + (cl-parsing-keywords (:test :test-not :key :from-end + (:start1 0) :end1 (:start2 0) :end2) () + (or cl-end1 (setq cl-end1 (length cl-seq1))) + (or cl-end2 (setq cl-end2 (length cl-seq2))) + (if (>= cl-start1 cl-end1) + (if cl-from-end cl-end2 cl-start2) + (let* ((cl-len (- cl-end1 cl-start1)) + (cl-first (cl-check-key (elt cl-seq1 cl-start1))) + (cl-if nil) cl-pos) + (setq cl-end2 (- cl-end2 (1- cl-len))) + (while (and (< cl-start2 cl-end2) + (setq cl-pos (cl-position cl-first cl-seq2 + cl-start2 cl-end2 cl-from-end)) + (apply 'mismatch cl-seq1 cl-seq2 + ':start1 (1+ cl-start1) ':end1 cl-end1 + ':start2 (1+ cl-pos) ':end2 (+ cl-pos cl-len) + ':from-end nil cl-keys)) + (if cl-from-end (setq cl-end2 cl-pos) (setq cl-start2 (1+ cl-pos)))) + (and (< cl-start2 cl-end2) cl-pos))))) + +(defun sort* (cl-seq cl-pred &rest cl-keys) + "Sort the argument SEQUENCE according to PREDICATE. +This is a destructive function; it reuses the storage of SEQUENCE if possible. +Keywords supported: :key" + (if (nlistp cl-seq) + (replace cl-seq (apply 'sort* (append cl-seq nil) cl-pred cl-keys)) + (cl-parsing-keywords (:key) () + (if (memq cl-key '(nil identity)) + (sort cl-seq cl-pred) + (sort cl-seq (function (lambda (cl-x cl-y) + (funcall cl-pred (funcall cl-key cl-x) + (funcall cl-key cl-y))))))))) + +(defun stable-sort (cl-seq cl-pred &rest cl-keys) + "Sort the argument SEQUENCE stably according to PREDICATE. +This is a destructive function; it reuses the storage of SEQUENCE if possible. +Keywords supported: :key" + (apply 'sort* cl-seq cl-pred cl-keys)) + +(defun merge (cl-type cl-seq1 cl-seq2 cl-pred &rest cl-keys) + "Destructively merge the two sequences to produce a new sequence. +TYPE is the sequence type to return, SEQ1 and SEQ2 are the two +argument sequences, and PRED is a `less-than' predicate on the elements. +Keywords supported: :key" + (or (listp cl-seq1) (setq cl-seq1 (append cl-seq1 nil))) + (or (listp cl-seq2) (setq cl-seq2 (append cl-seq2 nil))) + (cl-parsing-keywords (:key) () + (let ((cl-res nil)) + (while (and cl-seq1 cl-seq2) + (if (funcall cl-pred (cl-check-key (car cl-seq2)) + (cl-check-key (car cl-seq1))) + (cl-push (cl-pop cl-seq2) cl-res) + (cl-push (cl-pop cl-seq1) cl-res))) + (coerce (nconc (nreverse cl-res) cl-seq1 cl-seq2) cl-type)))) + +;;; See compiler macro in cl-macs.el +(defun member* (cl-item cl-list &rest cl-keys) + "Find the first occurrence of ITEM in LIST. +Return the sublist of LIST whose car is ITEM. +Keywords supported: :test :test-not :key" + (if cl-keys + (cl-parsing-keywords (:test :test-not :key :if :if-not) () + (while (and cl-list (not (cl-check-test cl-item (car cl-list)))) + (setq cl-list (cdr cl-list))) + cl-list) + (if (and (numberp cl-item) (not (integerp cl-item))) + (member cl-item cl-list) + (memq cl-item cl-list)))) + +(defun member-if (cl-pred cl-list &rest cl-keys) + "Find the first item satisfying PREDICATE in LIST. +Return the sublist of LIST whose car matches. +Keywords supported: :key" + (apply 'member* nil cl-list ':if cl-pred cl-keys)) + +(defun member-if-not (cl-pred cl-list &rest cl-keys) + "Find the first item not satisfying PREDICATE in LIST. +Return the sublist of LIST whose car matches. +Keywords supported: :key" + (apply 'member* nil cl-list ':if-not cl-pred cl-keys)) + +(defun cl-adjoin (cl-item cl-list &rest cl-keys) + (if (cl-parsing-keywords (:key) t + (apply 'member* (cl-check-key cl-item) cl-list cl-keys)) + cl-list + (cons cl-item cl-list))) + +;;; See compiler macro in cl-macs.el +(defun assoc* (cl-item cl-alist &rest cl-keys) + "Find the first item whose car matches ITEM in LIST. +Keywords supported: :test :test-not :key" + (if cl-keys + (cl-parsing-keywords (:test :test-not :key :if :if-not) () + (while (and cl-alist + (or (not (consp (car cl-alist))) + (not (cl-check-test cl-item (car (car cl-alist)))))) + (setq cl-alist (cdr cl-alist))) + (and cl-alist (car cl-alist))) + (if (and (numberp cl-item) (not (integerp cl-item))) + (assoc cl-item cl-alist) + (assq cl-item cl-alist)))) + +(defun assoc-if (cl-pred cl-list &rest cl-keys) + "Find the first item whose car satisfies PREDICATE in LIST. +Keywords supported: :key" + (apply 'assoc* nil cl-list ':if cl-pred cl-keys)) + +(defun assoc-if-not (cl-pred cl-list &rest cl-keys) + "Find the first item whose car does not satisfy PREDICATE in LIST. +Keywords supported: :key" + (apply 'assoc* nil cl-list ':if-not cl-pred cl-keys)) + +(defun rassoc* (cl-item cl-alist &rest cl-keys) + "Find the first item whose cdr matches ITEM in LIST. +Keywords supported: :test :test-not :key" + (if (or cl-keys (numberp cl-item)) + (cl-parsing-keywords (:test :test-not :key :if :if-not) () + (while (and cl-alist + (or (not (consp (car cl-alist))) + (not (cl-check-test cl-item (cdr (car cl-alist)))))) + (setq cl-alist (cdr cl-alist))) + (and cl-alist (car cl-alist))) + (rassq cl-item cl-alist))) + +(defun rassoc-if (cl-pred cl-list &rest cl-keys) + "Find the first item whose cdr satisfies PREDICATE in LIST. +Keywords supported: :key" + (apply 'rassoc* nil cl-list ':if cl-pred cl-keys)) + +(defun rassoc-if-not (cl-pred cl-list &rest cl-keys) + "Find the first item whose cdr does not satisfy PREDICATE in LIST. +Keywords supported: :key" + (apply 'rassoc* nil cl-list ':if-not cl-pred cl-keys)) + +(defun union (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-union operation. +The result list contains all items that appear in either LIST1 or LIST2. +This is a non-destructive function; it makes a copy of the data if necessary +to avoid corrupting the original LIST1 and LIST2. +Keywords supported: :test :test-not :key" + (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) + ((equal cl-list1 cl-list2) cl-list1) + (t + (or (>= (length cl-list1) (length cl-list2)) + (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1)))) + (while cl-list2 + (if (or cl-keys (numberp (car cl-list2))) + (setq cl-list1 (apply 'adjoin (car cl-list2) cl-list1 cl-keys)) + (or (memq (car cl-list2) cl-list1) + (cl-push (car cl-list2) cl-list1))) + (cl-pop cl-list2)) + cl-list1))) + +(defun nunion (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-union operation. +The result list contains all items that appear in either LIST1 or LIST2. +This is a destructive function; it reuses the storage of LIST1 and LIST2 +whenever possible. +Keywords supported: :test :test-not :key" + (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) + (t (apply 'union cl-list1 cl-list2 cl-keys)))) + +(defun intersection (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-intersection operation. +The result list contains all items that appear in both LIST1 and LIST2. +This is a non-destructive function; it makes a copy of the data if necessary +to avoid corrupting the original LIST1 and LIST2. +Keywords supported: :test :test-not :key" + (and cl-list1 cl-list2 + (if (equal cl-list1 cl-list2) cl-list1 + (cl-parsing-keywords (:key) (:test :test-not) + (let ((cl-res nil)) + (or (>= (length cl-list1) (length cl-list2)) + (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1)))) + (while cl-list2 + (if (if (or cl-keys (numberp (car cl-list2))) + (apply 'member* (cl-check-key (car cl-list2)) + cl-list1 cl-keys) + (memq (car cl-list2) cl-list1)) + (cl-push (car cl-list2) cl-res)) + (cl-pop cl-list2)) + cl-res))))) + +(defun nintersection (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-intersection operation. +The result list contains all items that appear in both LIST1 and LIST2. +This is a destructive function; it reuses the storage of LIST1 and LIST2 +whenever possible. +Keywords supported: :test :test-not :key" + (and cl-list1 cl-list2 (apply 'intersection cl-list1 cl-list2 cl-keys))) + +(defun set-difference (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-difference operation. +The result list contains all items that appear in LIST1 but not LIST2. +This is a non-destructive function; it makes a copy of the data if necessary +to avoid corrupting the original LIST1 and LIST2. +Keywords supported: :test :test-not :key" + (if (or (null cl-list1) (null cl-list2)) cl-list1 + (cl-parsing-keywords (:key) (:test :test-not) + (let ((cl-res nil)) + (while cl-list1 + (or (if (or cl-keys (numberp (car cl-list1))) + (apply 'member* (cl-check-key (car cl-list1)) + cl-list2 cl-keys) + (memq (car cl-list1) cl-list2)) + (cl-push (car cl-list1) cl-res)) + (cl-pop cl-list1)) + cl-res)))) + +(defun nset-difference (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-difference operation. +The result list contains all items that appear in LIST1 but not LIST2. +This is a destructive function; it reuses the storage of LIST1 and LIST2 +whenever possible. +Keywords supported: :test :test-not :key" + (if (or (null cl-list1) (null cl-list2)) cl-list1 + (apply 'set-difference cl-list1 cl-list2 cl-keys))) + +(defun set-exclusive-or (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-exclusive-or operation. +The result list contains all items that appear in exactly one of LIST1, LIST2. +This is a non-destructive function; it makes a copy of the data if necessary +to avoid corrupting the original LIST1 and LIST2. +Keywords supported: :test :test-not :key" + (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) + ((equal cl-list1 cl-list2) nil) + (t (append (apply 'set-difference cl-list1 cl-list2 cl-keys) + (apply 'set-difference cl-list2 cl-list1 cl-keys))))) + +(defun nset-exclusive-or (cl-list1 cl-list2 &rest cl-keys) + "Combine LIST1 and LIST2 using a set-exclusive-or operation. +The result list contains all items that appear in exactly one of LIST1, LIST2. +This is a destructive function; it reuses the storage of LIST1 and LIST2 +whenever possible. +Keywords supported: :test :test-not :key" + (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) + ((equal cl-list1 cl-list2) nil) + (t (nconc (apply 'nset-difference cl-list1 cl-list2 cl-keys) + (apply 'nset-difference cl-list2 cl-list1 cl-keys))))) + +(defun subsetp (cl-list1 cl-list2 &rest cl-keys) + "True if LIST1 is a subset of LIST2. +I.e., if every element of LIST1 also appears in LIST2. +Keywords supported: :test :test-not :key" + (cond ((null cl-list1) t) ((null cl-list2) nil) + ((equal cl-list1 cl-list2) t) + (t (cl-parsing-keywords (:key) (:test :test-not) + (while (and cl-list1 + (apply 'member* (cl-check-key (car cl-list1)) + cl-list2 cl-keys)) + (cl-pop cl-list1)) + (null cl-list1))))) + +(defun subst-if (cl-new cl-pred cl-tree &rest cl-keys) + "Substitute NEW for elements matching PREDICATE in TREE (non-destructively). +Return a copy of TREE with all matching elements replaced by NEW. +Keywords supported: :key" + (apply 'sublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys)) + +(defun subst-if-not (cl-new cl-pred cl-tree &rest cl-keys) + "Substitute NEW for elts not matching PREDICATE in TREE (non-destructively). +Return a copy of TREE with all non-matching elements replaced by NEW. +Keywords supported: :key" + (apply 'sublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys)) + +(defun nsubst (cl-new cl-old cl-tree &rest cl-keys) + "Substitute NEW for OLD everywhere in TREE (destructively). +Any element of TREE which is `eql' to OLD is changed to NEW (via a call +to `setcar'). +Keywords supported: :test :test-not :key" + (apply 'nsublis (list (cons cl-old cl-new)) cl-tree cl-keys)) + +(defun nsubst-if (cl-new cl-pred cl-tree &rest cl-keys) + "Substitute NEW for elements matching PREDICATE in TREE (destructively). +Any element of TREE which matches is changed to NEW (via a call to `setcar'). +Keywords supported: :key" + (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys)) + +(defun nsubst-if-not (cl-new cl-pred cl-tree &rest cl-keys) + "Substitute NEW for elements not matching PREDICATE in TREE (destructively). +Any element of TREE which matches is changed to NEW (via a call to `setcar'). +Keywords supported: :key" + (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys)) + +(defun sublis (cl-alist cl-tree &rest cl-keys) + "Perform substitutions indicated by ALIST in TREE (non-destructively). +Return a copy of TREE with all matching elements replaced. +Keywords supported: :test :test-not :key" + (cl-parsing-keywords (:test :test-not :key :if :if-not) () + (cl-sublis-rec cl-tree))) + +(defvar cl-alist) +(defun cl-sublis-rec (cl-tree) ; uses cl-alist/key/test*/if* + (let ((cl-temp (cl-check-key cl-tree)) (cl-p cl-alist)) + (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) + (setq cl-p (cdr cl-p))) + (if cl-p (cdr (car cl-p)) + (if (consp cl-tree) + (let ((cl-a (cl-sublis-rec (car cl-tree))) + (cl-d (cl-sublis-rec (cdr cl-tree)))) + (if (and (eq cl-a (car cl-tree)) (eq cl-d (cdr cl-tree))) + cl-tree + (cons cl-a cl-d))) + cl-tree)))) + +(defun nsublis (cl-alist cl-tree &rest cl-keys) + "Perform substitutions indicated by ALIST in TREE (destructively). +Any matching element of TREE is changed via a call to `setcar'. +Keywords supported: :test :test-not :key" + (cl-parsing-keywords (:test :test-not :key :if :if-not) () + (let ((cl-hold (list cl-tree))) + (cl-nsublis-rec cl-hold) + (car cl-hold)))) + +(defun cl-nsublis-rec (cl-tree) ; uses cl-alist/temp/p/key/test*/if* + (while (consp cl-tree) + (let ((cl-temp (cl-check-key (car cl-tree))) (cl-p cl-alist)) + (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) + (setq cl-p (cdr cl-p))) + (if cl-p (setcar cl-tree (cdr (car cl-p))) + (if (consp (car cl-tree)) (cl-nsublis-rec (car cl-tree)))) + (setq cl-temp (cl-check-key (cdr cl-tree)) cl-p cl-alist) + (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) + (setq cl-p (cdr cl-p))) + (if cl-p + (progn (setcdr cl-tree (cdr (car cl-p))) (setq cl-tree nil)) + (setq cl-tree (cdr cl-tree)))))) + +(defun tree-equal (cl-x cl-y &rest cl-keys) + "T if trees X and Y have `eql' leaves. +Atoms are compared by `eql'; cons cells are compared recursively. +Keywords supported: :test :test-not :key" + (cl-parsing-keywords (:test :test-not :key) () + (cl-tree-equal-rec cl-x cl-y))) + +(defun cl-tree-equal-rec (cl-x cl-y) + (while (and (consp cl-x) (consp cl-y) + (cl-tree-equal-rec (car cl-x) (car cl-y))) + (setq cl-x (cdr cl-x) cl-y (cdr cl-y))) + (and (not (consp cl-x)) (not (consp cl-y)) (cl-check-match cl-x cl-y))) + + +(run-hooks 'cl-seq-load-hook) + +;;; cl-seq.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cl.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,739 @@ +;;; cl.el --- Common Lisp extensions for GNU Emacs Lisp + +;; Copyright (C) 1993, 1997 Free Software Foundation, Inc. + +;; Author: Dave Gillespie +;; Maintainer: XEmacs Development Team +;; Version: 2.02 +;; Keywords: extensions, dumped, lisp + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; These are extensions to Emacs Lisp that provide a degree of +;; Common Lisp compatibility, beyond what is already built-in +;; in Emacs Lisp. +;; +;; This package was written by Dave Gillespie; it is a complete +;; rewrite of Cesar Quiroz's original cl.el package of December 1986. +;; +;; This package works with Emacs 18, Emacs 19, and XEmacs/Lucid Emacs 19. +;; +;; Bug reports, comments, and suggestions are welcome! + +;; This file contains the portions of the Common Lisp extensions +;; package which should always be present. + + +;;; Future notes: + +;; Once Emacs 19 becomes standard, many things in this package which are +;; messy for reasons of compatibility can be greatly simplified. For now, +;; I prefer to maintain one unified version. + + +;;; Change Log: + +;; Version 2.02 (30 Jul 93): +;; * Added "cl-compat.el" file, extra compatibility with old package. +;; * Added `lexical-let' and `lexical-let*'. +;; * Added `define-modify-macro', `callf', and `callf2'. +;; * Added `ignore-errors'. +;; * Changed `(setf (nthcdr N PLACE) X)' to work when N is zero. +;; * Merged `*gentemp-counter*' into `*gensym-counter*'. +;; * Extended `subseq' to allow negative START and END like `substring'. +;; * Added `in-ref', `across-ref', `elements of-ref' loop clauses. +;; * Added `concat', `vconcat' loop clauses. +;; * Cleaned up a number of compiler warnings. + +;; Version 2.01 (7 Jul 93): +;; * Added support for FSF version of Emacs 19. +;; * Added `add-hook' for Emacs 18 users. +;; * Added `defsubst*' and `symbol-macrolet'. +;; * Added `maplist', `mapc', `mapl', `mapcan', `mapcon'. +;; * Added `map', `concatenate', `reduce', `merge'. +;; * Added `revappend', `nreconc', `tailp', `tree-equal'. +;; * Added `assert', `check-type', `typecase', `typep', and `deftype'. +;; * Added destructuring and `&environment' support to `defmacro*'. +;; * Added destructuring to `loop', and added the following clauses: +;; `elements', `frames', `overlays', `intervals', `buffers', `key-seqs'. +;; * Renamed `delete' to `delete*' and `remove' to `remove*'. +;; * Completed support for all keywords in `remove*', `substitute', etc. +;; * Added `most-positive-float' and company. +;; * Fixed hash tables to work with latest Lucid Emacs. +;; * `proclaim' forms are no longer compile-time-evaluating; use `declaim'. +;; * Syntax for `warn' declarations has changed. +;; * Improved implementation of `random*'. +;; * Moved most sequence functions to a new file, cl-seq.el. +;; * Moved `eval-when' into cl-macs.el. +;; * Moved `pushnew' and `adjoin' to cl.el for most common cases. +;; * Moved `provide' forms down to ends of files. +;; * Changed expansion of `pop' to something that compiles to better code. +;; * Changed so that no patch is required for Emacs 19 byte compiler. +;; * Made more things dependent on `optimize' declarations. +;; * Added a partial implementation of struct print functions. +;; * Miscellaneous minor changes. + +;; Version 2.00: +;; * First public release of this package. + + +;;; Code: + +(defvar cl-emacs-type (cond ((or (and (fboundp 'epoch::version) + (symbol-value 'epoch::version)) + (string-lessp emacs-version "19")) 18) + ((string-match "XEmacs" emacs-version) + 'lucid) + (t 19))) + +(or (fboundp 'defalias) (fset 'defalias 'fset)) + +(defvar cl-optimize-speed 1) +(defvar cl-optimize-safety 1) + + +;;; Keywords used in this package. + +;;; XEmacs - keywords are done in Fintern(). +;;; +;;; (defconst :test ':test) +;;; (defconst :test-not ':test-not) +;;; (defconst :key ':key) +;;; (defconst :start ':start) +;;; (defconst :start1 ':start1) +;;; (defconst :start2 ':start2) +;;; (defconst :end ':end) +;;; (defconst :end1 ':end1) +;;; (defconst :end2 ':end2) +;;; (defconst :count ':count) +;;; (defconst :initial-value ':initial-value) +;;; (defconst :size ':size) +;;; (defconst :from-end ':from-end) +;;; (defconst :rehash-size ':rehash-size) +;;; (defconst :rehash-threshold ':rehash-threshold) +;;; (defconst :allow-other-keys ':allow-other-keys) + + +(defvar custom-print-functions nil + "This is a list of functions that format user objects for printing. +Each function is called in turn with three arguments: the object, the +stream, and the print level (currently ignored). If it is able to +print the object it returns true; otherwise it returns nil and the +printer proceeds to the next function on the list. + +This variable is not used at present, but it is defined in hopes that +a future Emacs interpreter will be able to use it.") + + +;;; Predicates. + +(defun eql (a b) ; See compiler macro in cl-macs.el + "T if the two args are the same Lisp object. +Floating-point numbers of equal value are `eql', but they may not be `eq'." + (if (numberp a) + (equal a b) + (eq a b))) + + +;;; Generalized variables. These macros are defined here so that they +;;; can safely be used in .emacs files. + +(defmacro incf (place &optional x) + "(incf PLACE [X]): increment PLACE by X (1 by default). +PLACE may be a symbol, or any generalized variable allowed by `setf'. +The return value is the incremented value of PLACE." + (if (symbolp place) + (list 'setq place (if x (list '+ place x) (list '1+ place))) + (list 'callf '+ place (or x 1)))) + +(defmacro decf (place &optional x) + "(decf PLACE [X]): decrement PLACE by X (1 by default). +PLACE may be a symbol, or any generalized variable allowed by `setf'. +The return value is the decremented value of PLACE." + (if (symbolp place) + (list 'setq place (if x (list '- place x) (list '1- place))) + (list 'callf '- place (or x 1)))) + +(defmacro pop (place) + "(pop PLACE): remove and return the head of the list stored in PLACE. +Analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE))), though more +careful about evaluating each argument only once and in the right order. +PLACE may be a symbol, or any generalized variable allowed by `setf'." + (if (symbolp place) + (list 'car (list 'prog1 place (list 'setq place (list 'cdr place)))) + (cl-do-pop place))) + +(defmacro push (x place) + "(push X PLACE): insert X at the head of the list stored in PLACE. +Analogous to (setf PLACE (cons X PLACE)), though more careful about +evaluating each argument only once and in the right order. PLACE may +be a symbol, or any generalized variable allowed by `setf'." + (if (symbolp place) (list 'setq place (list 'cons x place)) + (list 'callf2 'cons x place))) + +(defmacro pushnew (x place &rest keys) + "(pushnew X PLACE): insert X at the head of the list if not already there. +Like (push X PLACE), except that the list is unmodified if X is `eql' to +an element already on the list. +Keywords supported: :test :test-not :key" + (if (symbolp place) (list 'setq place (list* 'adjoin x place keys)) + (list* 'callf2 'adjoin x place keys))) + +(defun cl-set-elt (seq n val) + (if (listp seq) (setcar (nthcdr n seq) val) (aset seq n val))) + +(defun cl-set-nthcdr (n list x) + (if (<= n 0) x (setcdr (nthcdr (1- n) list) x) list)) + +(defun cl-set-buffer-substring (start end val) + (save-excursion (delete-region start end) + (goto-char start) + (insert val) + val)) + +(defun cl-set-substring (str start end val) + (if end (if (< end 0) (incf end (length str))) + (setq end (length str))) + (if (< start 0) (incf start str)) + (concat (and (> start 0) (substring str 0 start)) + val + (and (< end (length str)) (substring str end)))) + + +;;; Control structures. + +;;; These macros are so simple and so often-used that it's better to have +;;; them all the time than to load them from cl-macs.el. + +(defmacro when (cond &rest body) + "(when COND BODY...): if COND yields non-nil, do BODY, else return nil." + (list 'if cond (cons 'progn body))) + +(defmacro unless (cond &rest body) + "(unless COND BODY...): if COND yields nil, do BODY, else return nil." + (cons 'if (cons cond (cons nil body)))) + +(defun cl-map-extents (&rest cl-args) + (if (fboundp 'next-overlay-at) (apply 'cl-map-overlays cl-args) + (if (fboundp 'map-extents) (apply 'map-extents cl-args)))) + + +;;; Blocks and exits. + +(defalias 'cl-block-wrapper 'identity) +(defalias 'cl-block-throw 'throw) + + +;;; Multiple values. True multiple values are not supported, or even +;;; simulated. Instead, multiple-value-bind and friends simply expect +;;; the target form to return the values as a list. + +(defalias 'values 'list) +(defalias 'values-list 'identity) +(defalias 'multiple-value-list 'identity) +(defalias 'multiple-value-call 'apply) ; only works for one arg +(defalias 'nth-value 'nth) + + +;;; Macros. + +(defvar cl-macro-environment nil) +;; XEmacs: we renamed the internal function to macroexpand-internal +;; to avoid doc-file problems. +(defvar cl-old-macroexpand (prog1 (symbol-function 'macroexpand-internal) + (defalias 'macroexpand 'cl-macroexpand))) + +(defun cl-macroexpand (cl-macro &optional cl-env) + "Return result of expanding macros at top level of FORM. +If FORM is not a macro call, it is returned unchanged. +Otherwise, the macro is expanded and the expansion is considered +in place of FORM. When a non-macro-call results, it is returned. + +The second optional arg ENVIRONMENT species an environment of macro +definitions to shadow the loaded ones for use in file byte-compilation." + (let ((cl-macro-environment cl-env)) + (while (progn (setq cl-macro (funcall cl-old-macroexpand cl-macro cl-env)) + (and (symbolp cl-macro) + (cdr (assq (symbol-name cl-macro) cl-env)))) + (setq cl-macro (cadr (assq (symbol-name cl-macro) cl-env)))) + cl-macro)) + + +;;; Declarations. + +(defvar cl-compiling-file nil) +(defun cl-compiling-file () + (or cl-compiling-file + ;; XEmacs change +; (and (boundp 'outbuffer) (bufferp (symbol-value 'outbuffer)) +; (equal (buffer-name (symbol-value 'outbuffer)) +; " *Compiler Output*")) + (and (boundp 'byte-compile-outbuffer) + (bufferp (symbol-value 'byte-compile-outbuffer)) + (equal (buffer-name (symbol-value 'byte-compile-outbuffer)) + " *Compiler Output*")) + )) + +(defvar cl-proclaims-deferred nil) + +(defun proclaim (spec) + (if (fboundp 'cl-do-proclaim) (cl-do-proclaim spec t) + (push spec cl-proclaims-deferred)) + nil) + +(defmacro declaim (&rest specs) + (let ((body (mapcar (function (lambda (x) (list 'proclaim (list 'quote x)))) + specs))) + (if (cl-compiling-file) (list* 'eval-when '(compile load eval) body) + (cons 'progn body)))) ; avoid loading cl-macs.el for eval-when + + +;;; Symbols. + +(defun cl-random-time () + (let* ((time (copy-sequence (current-time-string))) (i (length time)) (v 0)) + (while (>= (decf i) 0) (setq v (+ (* v 3) (aref time i)))) + v)) + +(defvar *gensym-counter* (* (logand (cl-random-time) 1023) 100)) + + +;;; Numbers. + +(defun floatp-safe (x) + "T if OBJECT is a floating point number. +On Emacs versions that lack floating-point support, this function +always returns nil." + (and (numberp x) (not (integerp x)))) + +(defun plusp (x) + "T if NUMBER is positive." + (> x 0)) + +(defun minusp (x) + "T if NUMBER is negative." + (< x 0)) + +(defun oddp (x) + "T if INTEGER is odd." + (eq (logand x 1) 1)) + +(defun evenp (x) + "T if INTEGER is even." + (eq (logand x 1) 0)) + +(defun cl-abs (x) + "Return the absolute value of ARG." + (if (>= x 0) x (- x))) +(or (fboundp 'abs) (defalias 'abs 'cl-abs)) ; This is built-in to Emacs 19 + +(defvar *random-state* (vector 'cl-random-state-tag -1 30 (cl-random-time))) + +;;; We use `eval' in case VALBITS differs from compile-time to load-time. +(defconst most-positive-fixnum (eval '(lsh -1 -1))) +(defconst most-negative-fixnum (eval '(- -1 (lsh -1 -1)))) + +;;; The following are actually set by cl-float-limits. +(defconst most-positive-float nil) +(defconst most-negative-float nil) +(defconst least-positive-float nil) +(defconst least-negative-float nil) +(defconst least-positive-normalized-float nil) +(defconst least-negative-normalized-float nil) +(defconst float-epsilon nil) +(defconst float-negative-epsilon nil) + + +;;; Sequence functions. + +(defalias 'copy-seq 'copy-sequence) + +(defun mapcar* (cl-func cl-x &rest cl-rest) + "Apply FUNCTION to each element of SEQ, and make a list of the results. +If there are several SEQs, FUNCTION is called with that many arguments, +and mapping stops as soon as the shortest list runs out. With just one +SEQ, this is like `mapcar'. With several, it is like the Common Lisp +`mapcar' function extended to arbitrary sequence types." + (if cl-rest + (if (or (cdr cl-rest) (nlistp cl-x) (nlistp (car cl-rest))) + (cl-mapcar-many cl-func (cons cl-x cl-rest)) + (let ((cl-res nil) (cl-y (car cl-rest))) + (while (and cl-x cl-y) + (push (funcall cl-func (pop cl-x) (pop cl-y)) cl-res)) + (nreverse cl-res))) + (mapcar cl-func cl-x))) + + +;;; List functions. + +(defalias 'first 'car) +(defalias 'rest 'cdr) +(defalias 'endp 'null) + +(defun second (x) + "Return the second element of the list LIST." + (car (cdr x))) + +(defun third (x) + "Return the third element of the list LIST." + (car (cdr (cdr x)))) + +(defun fourth (x) + "Return the fourth element of the list LIST." + (nth 3 x)) + +(defun fifth (x) + "Return the fifth element of the list LIST." + (nth 4 x)) + +(defun sixth (x) + "Return the sixth element of the list LIST." + (nth 5 x)) + +(defun seventh (x) + "Return the seventh element of the list LIST." + (nth 6 x)) + +(defun eighth (x) + "Return the eighth element of the list LIST." + (nth 7 x)) + +(defun ninth (x) + "Return the ninth element of the list LIST." + (nth 8 x)) + +(defun tenth (x) + "Return the tenth element of the list LIST." + (nth 9 x)) + +(defun caar (x) + "Return the `car' of the `car' of X." + (car (car x))) + +(defun cadr (x) + "Return the `car' of the `cdr' of X." + (car (cdr x))) + +(defun cdar (x) + "Return the `cdr' of the `car' of X." + (cdr (car x))) + +(defun cddr (x) + "Return the `cdr' of the `cdr' of X." + (cdr (cdr x))) + +(defun caaar (x) + "Return the `car' of the `car' of the `car' of X." + (car (car (car x)))) + +(defun caadr (x) + "Return the `car' of the `car' of the `cdr' of X." + (car (car (cdr x)))) + +(defun cadar (x) + "Return the `car' of the `cdr' of the `car' of X." + (car (cdr (car x)))) + +(defun caddr (x) + "Return the `car' of the `cdr' of the `cdr' of X." + (car (cdr (cdr x)))) + +(defun cdaar (x) + "Return the `cdr' of the `car' of the `car' of X." + (cdr (car (car x)))) + +(defun cdadr (x) + "Return the `cdr' of the `car' of the `cdr' of X." + (cdr (car (cdr x)))) + +(defun cddar (x) + "Return the `cdr' of the `cdr' of the `car' of X." + (cdr (cdr (car x)))) + +(defun cdddr (x) + "Return the `cdr' of the `cdr' of the `cdr' of X." + (cdr (cdr (cdr x)))) + +(defun caaaar (x) + "Return the `car' of the `car' of the `car' of the `car' of X." + (car (car (car (car x))))) + +(defun caaadr (x) + "Return the `car' of the `car' of the `car' of the `cdr' of X." + (car (car (car (cdr x))))) + +(defun caadar (x) + "Return the `car' of the `car' of the `cdr' of the `car' of X." + (car (car (cdr (car x))))) + +(defun caaddr (x) + "Return the `car' of the `car' of the `cdr' of the `cdr' of X." + (car (car (cdr (cdr x))))) + +(defun cadaar (x) + "Return the `car' of the `cdr' of the `car' of the `car' of X." + (car (cdr (car (car x))))) + +(defun cadadr (x) + "Return the `car' of the `cdr' of the `car' of the `cdr' of X." + (car (cdr (car (cdr x))))) + +(defun caddar (x) + "Return the `car' of the `cdr' of the `cdr' of the `car' of X." + (car (cdr (cdr (car x))))) + +(defun cadddr (x) + "Return the `car' of the `cdr' of the `cdr' of the `cdr' of X." + (car (cdr (cdr (cdr x))))) + +(defun cdaaar (x) + "Return the `cdr' of the `car' of the `car' of the `car' of X." + (cdr (car (car (car x))))) + +(defun cdaadr (x) + "Return the `cdr' of the `car' of the `car' of the `cdr' of X." + (cdr (car (car (cdr x))))) + +(defun cdadar (x) + "Return the `cdr' of the `car' of the `cdr' of the `car' of X." + (cdr (car (cdr (car x))))) + +(defun cdaddr (x) + "Return the `cdr' of the `car' of the `cdr' of the `cdr' of X." + (cdr (car (cdr (cdr x))))) + +(defun cddaar (x) + "Return the `cdr' of the `cdr' of the `car' of the `car' of X." + (cdr (cdr (car (car x))))) + +(defun cddadr (x) + "Return the `cdr' of the `cdr' of the `car' of the `cdr' of X." + (cdr (cdr (car (cdr x))))) + +(defun cdddar (x) + "Return the `cdr' of the `cdr' of the `cdr' of the `car' of X." + (cdr (cdr (cdr (car x))))) + +(defun cddddr (x) + "Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X." + (cdr (cdr (cdr (cdr x))))) + +(defun last (x &optional n) + "Returns the last link in the list LIST. +With optional argument N, returns Nth-to-last link (default 1)." + (if n + (let ((m 0) (p x)) + (while (consp p) (incf m) (pop p)) + (if (<= n 0) p + (if (< n m) (nthcdr (- m n) x) x))) + (while (consp (cdr x)) (pop x)) + x)) + +(defun butlast (x &optional n) + "Returns a copy of LIST with the last N elements removed." + (if (and n (<= n 0)) x + (nbutlast (copy-sequence x) n))) + +(defun nbutlast (x &optional n) + "Modifies LIST to remove the last N elements." + (let ((m (length x))) + (or n (setq n 1)) + (and (< n m) + (progn + (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil)) + x)))) + +(defun list* (arg &rest rest) ; See compiler macro in cl-macs.el + "Return a new list with specified args as elements, cons'd to last arg. +Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to +`(cons A (cons B (cons C D)))'." + (cond ((not rest) arg) + ((not (cdr rest)) (cons arg (car rest))) + (t (let* ((n (length rest)) + (copy (copy-sequence rest)) + (last (nthcdr (- n 2) copy))) + (setcdr last (car (cdr last))) + (cons arg copy))))) + +(defun ldiff (list sublist) + "Return a copy of LIST with the tail SUBLIST removed." + (let ((res nil)) + (while (and (consp list) (not (eq list sublist))) + (push (pop list) res)) + (nreverse res))) + +(defun copy-list (list) + "Return a copy of a list, which may be a dotted list. +The elements of the list are not copied, just the list structure itself." + (if (consp list) + (let ((res nil)) + (while (consp list) (push (pop list) res)) + (prog1 (nreverse res) (setcdr res list))) + (car list))) + +(defun cl-maclisp-member (item list) + (while (and list (not (equal item (car list)))) (setq list (cdr list))) + list) + +;;; Define an Emacs 19-compatible `member' for the benefit of Emacs 18 users. +(or (and (fboundp 'member) (subrp (symbol-function 'member))) + (defalias 'member 'cl-maclisp-member)) + +(defalias 'cl-member 'memq) ; for compatibility with old CL package +(defalias 'cl-floor 'floor*) +(defalias 'cl-ceiling 'ceiling*) +(defalias 'cl-truncate 'truncate*) +(defalias 'cl-round 'round*) +(defalias 'cl-mod 'mod*) + +(defun adjoin (cl-item cl-list &rest cl-keys) ; See compiler macro in cl-macs + "Return ITEM consed onto the front of LIST only if it's not already there. +Otherwise, return LIST unmodified. +Keywords supported: :test :test-not :key" + (cond ((or (equal cl-keys '(:test eq)) + (and (null cl-keys) (not (numberp cl-item)))) + (if (memq cl-item cl-list) cl-list (cons cl-item cl-list))) + ((or (equal cl-keys '(:test equal)) (null cl-keys)) + (if (member cl-item cl-list) cl-list (cons cl-item cl-list))) + (t (apply 'cl-adjoin cl-item cl-list cl-keys)))) + +(defun subst (cl-new cl-old cl-tree &rest cl-keys) + "Substitute NEW for OLD everywhere in TREE (non-destructively). +Return a copy of TREE with all elements `eql' to OLD replaced by NEW. +Keywords supported: :test :test-not :key" + (if (or cl-keys (and (numberp cl-old) (not (integerp cl-old)))) + (apply 'sublis (list (cons cl-old cl-new)) cl-tree cl-keys) + (cl-do-subst cl-new cl-old cl-tree))) + +(defun cl-do-subst (cl-new cl-old cl-tree) + (cond ((eq cl-tree cl-old) cl-new) + ((consp cl-tree) + (let ((a (cl-do-subst cl-new cl-old (car cl-tree))) + (d (cl-do-subst cl-new cl-old (cdr cl-tree)))) + (if (and (eq a (car cl-tree)) (eq d (cdr cl-tree))) + cl-tree (cons a d)))) + (t cl-tree))) + +(defun acons (a b c) (cons (cons a b) c)) +(defun pairlis (a b &optional c) (nconc (mapcar* 'cons a b) c)) + + +;;; Miscellaneous. + +;; XEmacs change +(define-error 'cl-assertion-failed "Assertion failed") + +;;; This is defined in Emacs 19; define it here for Emacs 18 users. +(defun cl-add-hook (hook func &optional append) + "Add to hook variable HOOK the function FUNC. +FUNC is not added if it already appears on the list stored in HOOK." + (let ((old (and (boundp hook) (symbol-value hook)))) + (and (listp old) (not (eq (car old) 'lambda)) + (setq old (list old))) + (and (not (member func old)) + (set hook (if append (nconc old (list func)) (cons func old)))))) +(or (fboundp 'add-hook) (defalias 'add-hook 'cl-add-hook)) + +;; XEmacs change +;(load "cl-defs") + +;;; Define data for indentation and edebug. +(mapcar (function + (lambda (entry) + (mapcar (function + (lambda (func) + (put func 'lisp-indent-function (nth 1 entry)) + (put func 'lisp-indent-hook (nth 1 entry)) + (or (get func 'edebug-form-spec) + (put func 'edebug-form-spec (nth 2 entry))))) + (car entry)))) + '(((defun* defmacro*) defun) + ((function*) nil + (&or symbolp ([&optional 'macro] 'lambda (&rest sexp) &rest form))) + ((eval-when) 1 (sexp &rest form)) + ((when unless) 1 (&rest form)) + ((declare) nil (&rest sexp)) + ((the) 1 (sexp &rest form)) + ((case ecase typecase etypecase) 1 (form &rest (sexp &rest form))) + ((block return-from) 1 (sexp &rest form)) + ((return) nil (&optional form)) + ((do do*) 2 ((&rest &or symbolp (symbolp &optional form form)) + (form &rest form) + &rest form)) + ((dolist dotimes) 1 ((symbolp form &rest form) &rest form)) + ((do-symbols) 1 ((symbolp form &optional form form) &rest form)) + ((do-all-symbols) 1 ((symbolp form &optional form) &rest form)) + ((psetq setf psetf) nil edebug-setq-form) + ((progv) 2 (&rest form)) + ((flet labels macrolet) 1 + ((&rest (sexp sexp &rest form)) &rest form)) + ((symbol-macrolet lexical-let lexical-let*) 1 + ((&rest &or symbolp (symbolp form)) &rest form)) + ((multiple-value-bind) 2 ((&rest symbolp) &rest form)) + ((multiple-value-setq) 1 ((&rest symbolp) &rest form)) + ((incf decf remf pop push pushnew shiftf rotatef) nil (&rest form)) + ((letf letf*) 1 ((&rest (&rest form)) &rest form)) + ((callf destructuring-bind) 2 (sexp form &rest form)) + ((callf2) 3 (sexp form form &rest form)) + ((loop) defun (&rest &or symbolp form)) + ((ignore-errors) 0 (&rest form)))) + + +;;; This goes here so that cl-macs can find it if it loads right now. +(provide 'cl-19) ; usage: (require 'cl-19 "cl") + + +;;; Things to do after byte-compiler is loaded. +;;; As a side effect, we cause cl-macs to be loaded when compiling, so +;;; that the compiler-macros defined there will be present. + +(defvar cl-hacked-flag nil) +(defun cl-hack-byte-compiler () + (if (and (not cl-hacked-flag) (fboundp 'byte-compile-file-form)) + (progn + (cl-compile-time-init) ; in cl-macs.el + (setq cl-hacked-flag t)))) + +;;; Try it now in case the compiler has already been loaded. +(cl-hack-byte-compiler) + +;;; Also make a hook in case compiler is loaded after this file. +;;; The compiler doesn't call any hooks when it loads or runs, but +;;; we can take advantage of the fact that emacs-lisp-mode will be +;;; called when the compiler reads in the file to be compiled. +;;; BUG: If the first compilation is `byte-compile' rather than +;;; `byte-compile-file', we lose. Oh, well. +(add-hook 'emacs-lisp-mode-hook 'cl-hack-byte-compiler) + + +;;; The following ensures that packages which expect the old-style cl.el +;;; will be happy with this one. + +(provide 'cl) + +(provide 'mini-cl) ; for Epoch + +(run-hooks 'cl-load-hook) + +;;; cl.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl/auto-autoloads.el --- a/lisp/cl/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,331 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'cl-autoloads) (error "Already loaded")) - -(provide 'cl-autoloads) - -;;;### (autoloads (compiler-macroexpand define-compiler-macro ignore-errors assert check-type typep deftype cl-struct-setf-expander defstruct define-modify-macro callf2 callf letf* letf rotatef shiftf remf cl-do-pop psetf setf get-setf-method defsetf define-setf-method declare the locally multiple-value-setq multiple-value-bind lexical-let* lexical-let symbol-macrolet macrolet labels flet progv psetq do-all-symbols do-symbols dotimes dolist do* do loop return-from return block etypecase typecase ecase case load-time-value eval-when destructuring-bind function* defmacro* defun* gentemp gensym cl-compile-time-init) "cl-macs" "cl/cl-macs.el") - -(autoload 'cl-compile-time-init "cl-macs" nil nil nil) - -(autoload 'gensym "cl-macs" "\ -Generate a new uninterned symbol. -The name is made by appending a number to PREFIX, default \"G\"." nil nil) - -(autoload 'gentemp "cl-macs" "\ -Generate a new interned symbol with a unique name. -The name is made by appending a number to PREFIX, default \"G\"." nil nil) - -(autoload 'defun* "cl-macs" "\ -(defun* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. -Like normal `defun', except ARGLIST allows full Common Lisp conventions, -and BODY is implicitly surrounded by (block NAME ...)." nil 'macro) - -(autoload 'defmacro* "cl-macs" "\ -(defmacro* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a macro. -Like normal `defmacro', except ARGLIST allows full Common Lisp conventions, -and BODY is implicitly surrounded by (block NAME ...)." nil 'macro) - -(autoload 'function* "cl-macs" "\ -(function* SYMBOL-OR-LAMBDA): introduce a function. -Like normal `function', except that if argument is a lambda form, its -ARGLIST allows full Common Lisp conventions." nil 'macro) - -(autoload 'destructuring-bind "cl-macs" nil nil 'macro) - -(autoload 'eval-when "cl-macs" "\ -(eval-when (WHEN...) BODY...): control when BODY is evaluated. -If `compile' is in WHEN, BODY is evaluated when compiled at top-level. -If `load' is in WHEN, BODY is evaluated when loaded after top-level compile. -If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level." nil 'macro) - -(autoload 'load-time-value "cl-macs" "\ -Like `progn', but evaluates the body at load time. -The result of the body appears to the compiler as a quoted constant." nil 'macro) - -(autoload 'case "cl-macs" "\ -(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. -Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared -against each key in each KEYLIST; the corresponding BODY is evaluated. -If no clause succeeds, case returns nil. A single atom may be used in -place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is -allowed only in the final clause, and matches if no other keys match. -Key values are compared by `eql'." nil 'macro) - -(autoload 'ecase "cl-macs" "\ -(ecase EXPR CLAUSES...): like `case', but error if no case fits. -`otherwise'-clauses are not allowed." nil 'macro) - -(autoload 'typecase "cl-macs" "\ -(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. -Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it -satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, -typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the -final clause, and matches if no other keys match." nil 'macro) - -(autoload 'etypecase "cl-macs" "\ -(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits. -`otherwise'-clauses are not allowed." nil 'macro) - -(autoload 'block "cl-macs" "\ -(block NAME BODY...): define a lexically-scoped block named NAME. -NAME may be any symbol. Code inside the BODY forms can call `return-from' -to jump prematurely out of the block. This differs from `catch' and `throw' -in two respects: First, the NAME is an unevaluated symbol rather than a -quoted symbol or other form; and second, NAME is lexically rather than -dynamically scoped: Only references to it within BODY will work. These -references may appear inside macro expansions, but not inside functions -called from BODY." nil 'macro) - -(autoload 'return "cl-macs" "\ -(return [RESULT]): return from the block named nil. -This is equivalent to `(return-from nil RESULT)'." nil 'macro) - -(autoload 'return-from "cl-macs" "\ -(return-from NAME [RESULT]): return from the block named NAME. -This jump out to the innermost enclosing `(block NAME ...)' form, -returning RESULT from that form (or nil if RESULT is omitted). -This is compatible with Common Lisp, but note that `defun' and -`defmacro' do not create implicit blocks as they do in Common Lisp." nil 'macro) - -(autoload 'loop "cl-macs" "\ -(loop CLAUSE...): The Common Lisp `loop' macro. -Valid clauses are: - for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, - for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, - for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, - always COND, never COND, thereis COND, collect EXPR into VAR, - append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, - count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, - if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], - unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], - do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, - finally return EXPR, named NAME." nil 'macro) - -(autoload 'do "cl-macs" "\ -The Common Lisp `do' loop. -Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" nil 'macro) - -(autoload 'do* "cl-macs" "\ -The Common Lisp `do*' loop. -Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" nil 'macro) - -(autoload 'dolist "cl-macs" "\ -(dolist (VAR LIST [RESULT]) BODY...): loop over a list. -Evaluate BODY with VAR bound to each `car' from LIST, in turn. -Then evaluate RESULT to get return value, default nil." nil 'macro) - -(autoload 'dotimes "cl-macs" "\ -(dotimes (VAR COUNT [RESULT]) BODY...): loop a certain number of times. -Evaluate BODY with VAR bound to successive integers from 0, inclusive, -to COUNT, exclusive. Then evaluate RESULT to get return value, default -nil." nil 'macro) - -(autoload 'do-symbols "cl-macs" "\ -(dosymbols (VAR [OBARRAY [RESULT]]) BODY...): loop over all symbols. -Evaluate BODY with VAR bound to each interned symbol, or to each symbol -from OBARRAY." nil 'macro) - -(autoload 'do-all-symbols "cl-macs" nil nil 'macro) - -(autoload 'psetq "cl-macs" "\ -(psetq SYM VAL SYM VAL ...): set SYMs to the values VALs in parallel. -This is like `setq', except that all VAL forms are evaluated (in order) -before assigning any symbols SYM to the corresponding values." nil 'macro) - -(autoload 'progv "cl-macs" "\ -(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY. -The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. -Each SYMBOL in the first list is bound to the corresponding VALUE in the -second list (or made unbound if VALUES is shorter than SYMBOLS); then the -BODY forms are executed and their result is returned. This is much like -a `let' form, except that the list of symbols can be computed at run-time." nil 'macro) - -(autoload 'flet "cl-macs" "\ -(flet ((FUNC ARGLIST BODY...) ...) FORM...): make temporary function defns. -This is an analogue of `let' that operates on the function cell of FUNC -rather than its value cell. The FORMs are evaluated with the specified -function definitions in place, then the definitions are undone (the FUNCs -go back to their previous definitions, or lack thereof)." nil 'macro) - -(autoload 'labels "cl-macs" "\ -(labels ((FUNC ARGLIST BODY...) ...) FORM...): make temporary func bindings. -This is like `flet', except the bindings are lexical instead of dynamic. -Unlike `flet', this macro is fully complaint with the Common Lisp standard." nil 'macro) - -(autoload 'macrolet "cl-macs" "\ -(macrolet ((NAME ARGLIST BODY...) ...) FORM...): make temporary macro defns. -This is like `flet', but for macros instead of functions." nil 'macro) - -(autoload 'symbol-macrolet "cl-macs" "\ -(symbol-macrolet ((NAME EXPANSION) ...) FORM...): make symbol macro defns. -Within the body FORMs, references to the variable NAME will be replaced -by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)." nil 'macro) - -(autoload 'lexical-let "cl-macs" "\ -(lexical-let BINDINGS BODY...): like `let', but lexically scoped. -The main visible difference is that lambdas inside BODY will create -lexical closures as in Common Lisp." nil 'macro) - -(autoload 'lexical-let* "cl-macs" "\ -(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped. -The main visible difference is that lambdas inside BODY will create -lexical closures as in Common Lisp." nil 'macro) - -(autoload 'multiple-value-bind "cl-macs" "\ -(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values. -FORM must return a list; the BODY is then executed with the first N elements -of this list bound (`let'-style) to each of the symbols SYM in turn. This -is analogous to the Common Lisp `multiple-value-bind' macro, using lists to -simulate true multiple return values. For compatibility, (values A B C) is -a synonym for (list A B C)." nil 'macro) - -(autoload 'multiple-value-setq "cl-macs" "\ -(multiple-value-setq (SYM SYM...) FORM): collect multiple return values. -FORM must return a list; the first N elements of this list are stored in -each of the symbols SYM in turn. This is analogous to the Common Lisp -`multiple-value-setq' macro, using lists to simulate true multiple return -values. For compatibility, (values A B C) is a synonym for (list A B C)." nil 'macro) - -(autoload 'locally "cl-macs" nil nil 'macro) - -(autoload 'the "cl-macs" nil nil 'macro) - -(autoload 'declare "cl-macs" nil nil 'macro) - -(autoload 'define-setf-method "cl-macs" "\ -(define-setf-method NAME ARGLIST BODY...): define a `setf' method. -This method shows how to handle `setf's to places of the form (NAME ARGS...). -The argument forms ARGS are bound according to ARGLIST, as if NAME were -going to be expanded as a macro, then the BODY forms are executed and must -return a list of five elements: a temporary-variables list, a value-forms -list, a store-variables list (of length one), a store-form, and an access- -form. See `defsetf' for a simpler way to define most setf-methods." nil 'macro) - -(autoload 'defsetf "cl-macs" "\ -(defsetf NAME FUNC): define a `setf' method. -This macro is an easy-to-use substitute for `define-setf-method' that works -well for simple place forms. In the simple `defsetf' form, `setf's of -the form (setf (NAME ARGS...) VAL) are transformed to function or macro -calls of the form (FUNC ARGS... VAL). Example: (defsetf aref aset). -Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). -Here, the above `setf' call is expanded by binding the argument forms ARGS -according to ARGLIST, binding the value form VAL to STORE, then executing -BODY, which must return a Lisp form that does the necessary `setf' operation. -Actually, ARGLIST and STORE may be bound to temporary variables which are -introduced automatically to preserve proper execution order of the arguments. -Example: (defsetf nth (n x) (v) (list 'setcar (list 'nthcdr n x) v))." nil 'macro) - -(autoload 'get-setf-method "cl-macs" "\ -Return a list of five values describing the setf-method for PLACE. -PLACE may be any Lisp form which can appear as the PLACE argument to -a macro like `setf' or `incf'." nil nil) - -(autoload 'setf "cl-macs" "\ -(setf PLACE VAL PLACE VAL ...): set each PLACE to the value of its VAL. -This is a generalized version of `setq'; the PLACEs may be symbolic -references such as (car x) or (aref x i), as well as plain symbols. -For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y). -The return value is the last VAL in the list." nil 'macro) - -(autoload 'psetf "cl-macs" "\ -(psetf PLACE VAL PLACE VAL ...): set PLACEs to the values VALs in parallel. -This is like `setf', except that all VAL forms are evaluated (in order) -before assigning any PLACEs to the corresponding values." nil 'macro) - -(autoload 'cl-do-pop "cl-macs" nil nil nil) - -(autoload 'remf "cl-macs" "\ -(remf PLACE TAG): remove TAG from property list PLACE. -PLACE may be a symbol, or any generalized variable allowed by `setf'. -The form returns true if TAG was found and removed, nil otherwise." nil 'macro) - -(autoload 'shiftf "cl-macs" "\ -(shiftf PLACE PLACE... VAL): shift left among PLACEs. -Example: (shiftf A B C) sets A to B, B to C, and returns the old A. -Each PLACE may be a symbol, or any generalized variable allowed by `setf'." nil 'macro) - -(autoload 'rotatef "cl-macs" "\ -(rotatef PLACE...): rotate left among PLACEs. -Example: (rotatef A B C) sets A to B, B to C, and C to A. It returns nil. -Each PLACE may be a symbol, or any generalized variable allowed by `setf'." nil 'macro) - -(autoload 'letf "cl-macs" "\ -(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. -This is the analogue of `let', but with generalized variables (in the -sense of `setf') for the PLACEs. Each PLACE is set to the corresponding -VALUE, then the BODY forms are executed. On exit, either normally or -because of a `throw' or error, the PLACEs are set back to their original -values. Note that this macro is *not* available in Common Lisp. -As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', -the PLACE is not modified before executing BODY." nil 'macro) - -(autoload 'letf* "cl-macs" "\ -(letf* ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. -This is the analogue of `let*', but with generalized variables (in the -sense of `setf') for the PLACEs. Each PLACE is set to the corresponding -VALUE, then the BODY forms are executed. On exit, either normally or -because of a `throw' or error, the PLACEs are set back to their original -values. Note that this macro is *not* available in Common Lisp. -As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', -the PLACE is not modified before executing BODY." nil 'macro) - -(autoload 'callf "cl-macs" "\ -(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...). -FUNC should be an unquoted function name. PLACE may be a symbol, -or any generalized variable allowed by `setf'." nil 'macro) - -(autoload 'callf2 "cl-macs" "\ -(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...). -Like `callf', but PLACE is the second argument of FUNC, not the first." nil 'macro) - -(autoload 'define-modify-macro "cl-macs" "\ -(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro. -If NAME is called, it combines its PLACE argument with the other arguments -from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" nil 'macro) - -(autoload 'defstruct "cl-macs" "\ -(defstruct (NAME OPTIONS...) (SLOT SLOT-OPTS...)...): define a struct type. -This macro defines a new Lisp data type called NAME, which contains data -stored in SLOTs. This defines a `make-NAME' constructor, a `copy-NAME' -copier, a `NAME-p' predicate, and setf-able `NAME-SLOT' accessors." nil 'macro) - -(autoload 'cl-struct-setf-expander "cl-macs" nil nil nil) - -(autoload 'deftype "cl-macs" "\ -(deftype NAME ARGLIST BODY...): define NAME as a new data type. -The type name can then be used in `typecase', `check-type', etc." nil 'macro) - -(autoload 'typep "cl-macs" "\ -Check that OBJECT is of type TYPE. -TYPE is a Common Lisp-style type specifier." nil nil) - -(autoload 'check-type "cl-macs" "\ -Verify that FORM is of type TYPE; signal an error if not. -STRING is an optional description of the desired type." nil 'macro) - -(autoload 'assert "cl-macs" "\ -Verify that FORM returns non-nil; signal an error if not. -Second arg SHOW-ARGS means to include arguments of FORM in message. -Other args STRING and ARGS... are arguments to be passed to `error'. -They are not evaluated unless the assertion fails. If STRING is -omitted, a default message listing FORM itself is used." nil 'macro) - -(autoload 'ignore-errors "cl-macs" "\ -Execute FORMS; if an error occurs, return nil. -Otherwise, return result of last FORM." nil 'macro) - -(autoload 'define-compiler-macro "cl-macs" "\ -(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro. -This is like `defmacro', but macro expansion occurs only if the call to -FUNC is compiled (i.e., not interpreted). Compiler macros should be used -for optimizing the way calls to FUNC are compiled; the form returned by -BODY should do the same thing as a call to the normal function called -FUNC, though possibly more efficiently. Note that, like regular macros, -compiler macros are expanded repeatedly until no further expansions are -possible. Unlike regular macros, BODY can decide to \"punt\" and leave the -original function call alone by declaring an initial `&whole foo' parameter -and then returning foo." nil 'macro) - -(autoload 'compiler-macroexpand "cl-macs" nil nil nil) - -;;;*** diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl/cl-compat.el --- a/lisp/cl/cl-compat.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility) - -;; Copyright (C) 1993 Free Software Foundation, Inc. - -;; Author: Dave Gillespie -;; Version: 2.02 -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; These are extensions to Emacs Lisp that provide a degree of -;; Common Lisp compatibility, beyond what is already built-in -;; in Emacs Lisp. -;; -;; This package was written by Dave Gillespie; it is a complete -;; rewrite of Cesar Quiroz's original cl.el package of December 1986. -;; -;; This package works with Emacs 18, Emacs 19, and XEmacs/Lucid Emacs 19. -;; -;; Bug reports, comments, and suggestions are welcome! - -;; This file contains emulations of internal routines of the older -;; CL package which users may have called directly from their code. -;; Use (require 'cl-compat) to get these routines. - -;; See cl.el for Change Log. - - -;;; Code: - -;; Require at load-time, but not when compiling cl-compat. -(or (featurep 'cl) (require 'cl)) - - -;;; Keyword routines not supported by new package. - -(defmacro defkeyword (x &optional doc) - (list* 'defconst x (list 'quote x) (and doc (list doc)))) - -(defun keywordp (sym) - (and (symbolp sym) (eq (aref (symbol-name sym) 0) ?\:) (set sym sym))) - -(defun keyword-of (sym) - (or (keywordp sym) (keywordp (intern (format ":%s" sym))))) - - -;;; Multiple values. Note that the new package uses a different -;;; convention for multiple values. The following definitions -;;; emulate the old convention; all function names have been changed -;;; by capitalizing the first letter: Values, Multiple-value-*, -;;; to avoid conflict with the new-style definitions in cl-macs. - -(put 'Multiple-value-bind 'lisp-indent-function 2) -(put 'Multiple-value-setq 'lisp-indent-function 2) -(put 'Multiple-value-call 'lisp-indent-function 1) -(put 'Multiple-value-prog1 'lisp-indent-function 1) - -(defvar *mvalues-values* nil) - -(defun Values (&rest val-forms) - (setq *mvalues-values* val-forms) - (car val-forms)) - -(defun Values-list (val-forms) - (apply 'values val-forms)) - -(defmacro Multiple-value-list (form) - (list 'let* (list '(*mvalues-values* nil) (list '*mvalues-temp* form)) - '(or (and (eq *mvalues-temp* (car *mvalues-values*)) *mvalues-values*) - (list *mvalues-temp*)))) - -(defmacro Multiple-value-call (function &rest args) - (list 'apply function - (cons 'append - (mapcar (function (lambda (x) (list 'Multiple-value-list x))) - args)))) - -(defmacro Multiple-value-bind (vars form &rest body) - (list* 'multiple-value-bind vars (list 'Multiple-value-list form) body)) - -(defmacro Multiple-value-setq (vars form) - (list 'multiple-value-setq vars (list 'Multiple-value-list form))) - -(defmacro Multiple-value-prog1 (form &rest body) - (list 'prog1 form (list* 'let '((*mvalues-values* nil)) body))) - - -;;; Routines for parsing keyword arguments. - -(defun build-klist (arglist keys &optional allow-others) - (let ((res (Multiple-value-call 'mapcar* 'cons (unzip-lists arglist)))) - (or allow-others - (let ((bad (set-difference (mapcar 'car res) keys))) - (if bad (error "Bad keywords: %s not in %s" bad keys)))) - res)) - -(defun extract-from-klist (klist key &optional def) - (let ((res (assq key klist))) (if res (cdr res) def))) - -(defun keyword-argument-supplied-p (klist key) - (assq key klist)) - -(defun elt-satisfies-test-p (item elt klist) - (let ((test-not (cdr (assq ':test-not klist))) - (test (cdr (assq ':test klist))) - (key (cdr (assq ':key klist)))) - (if key (setq elt (funcall key elt))) - (if test-not (not (funcall test-not item elt)) - (funcall (or test 'eql) item elt)))) - - -;;; Rounding functions with old-style multiple value returns. - -(defun cl-floor (a &optional b) (Values-list (floor* a b))) -(defun cl-ceiling (a &optional b) (Values-list (ceiling* a b))) -(defun cl-round (a &optional b) (Values-list (round* a b))) -(defun cl-truncate (a &optional b) (Values-list (truncate* a b))) - -(defun safe-idiv (a b) - (let* ((q (/ (abs a) (abs b))) - (s (* (signum a) (signum b)))) - (Values q (- a (* s q b)) s))) - - -;; Internal routines. - -(defun pair-with-newsyms (oldforms) - (let ((newsyms (mapcar (function (lambda (x) (gensym))) oldforms))) - (Values (mapcar* 'list newsyms oldforms) newsyms))) - -(defun zip-lists (evens odds) - (mapcan 'list evens odds)) - -(defun unzip-lists (list) - (let ((e nil) (o nil)) - (while list - (setq e (cons (car list) e) o (cons (cadr list) o) list (cddr list))) - (Values (nreverse e) (nreverse o)))) - -(defun reassemble-argslists (list) - (let ((n (apply 'min (mapcar 'length list))) (res nil)) - (while (>= (setq n (1- n)) 0) - (setq res (cons (mapcar (function (lambda (x) (elt x n))) list) res))) - res)) - -(defun duplicate-symbols-p (list) - (let ((res nil)) - (while list - (if (memq (car list) (cdr list)) (setq res (cons (car list) res))) - (setq list (cdr list))) - res)) - - -;;; Setf internals. - -(defun setnth (n list x) - (setcar (nthcdr n list) x)) - -(defun setnthcdr (n list x) - (setcdr (nthcdr (1- n) list) x)) - -(defun setelt (seq n x) - (if (consp seq) (setcar (nthcdr n seq) x) (aset seq n x))) - - -;;; Functions omitted: case-clausify, check-do-stepforms, check-do-endforms, -;;; extract-do-inits, extract-do[*]-steps, select-stepping-forms, -;;; elt-satisfies-if[-not]-p, with-keyword-args, mv-bind-clausify, -;;; all names with embedded `$'. - - -(provide 'cl-compat) - -;;; cl-compat.el ends here - diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl/cl-extra.el --- a/lisp/cl/cl-extra.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,936 +0,0 @@ -;;; cl-extra.el --- Common Lisp extensions for GNU Emacs Lisp (part two) - -;; Copyright (C) 1993 Free Software Foundation, Inc. - -;; Author: Dave Gillespie -;; Version: 2.02 -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; These are extensions to Emacs Lisp that provide a degree of -;; Common Lisp compatibility, beyond what is already built-in -;; in Emacs Lisp. -;; -;; This package was written by Dave Gillespie; it is a complete -;; rewrite of Cesar Quiroz's original cl.el package of December 1986. -;; -;; This package works with Emacs 18, Emacs 19, and XEmacs/Lucid Emacs 19. -;; -;; Bug reports, comments, and suggestions are welcome! - -;; This file contains portions of the Common Lisp extensions -;; package which are autoloaded since they are relatively obscure. - -;; See cl.el for Change Log. - - -;;; Code: - -(or (memq 'cl-19 features) - (error "Tried to load `cl-extra' before `cl'!")) - - -;;; We define these here so that this file can compile without having -;;; loaded the cl.el file already. - -(defmacro cl-push (x place) (list 'setq place (list 'cons x place))) -(defmacro cl-pop (place) - (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) - -(defvar cl-emacs-type) - - -;;; Type coercion. - -(defun coerce (x type) - "Coerce OBJECT to type TYPE. -TYPE is a Common Lisp type specifier." - (cond ((eq type 'list) (if (listp x) x (append x nil))) - ((eq type 'vector) (if (vectorp x) x (vconcat x))) - ((eq type 'string) (if (stringp x) x (concat x))) - ((eq type 'array) (if (arrayp x) x (vconcat x))) - ((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0)) - ((and (eq type 'character) (symbolp x)) (coerce (symbol-name x) type)) - ((eq type 'float) (float x)) - ((typep x type) x) - (t (error "Can't coerce %s to type %s" x type)))) - - -;;; Predicates. - -(defun equalp (x y) - "T if two Lisp objects have similar structures and contents. -This is like `equal', except that it accepts numerically equal -numbers of different types (float vs. integer), and also compares -strings case-insensitively." - (cond ((eq x y) t) - ((stringp x) - (and (stringp y) (= (length x) (length y)) - (or (string-equal x y) - (string-equal (downcase x) (downcase y))))) ; lazy but simple! - ((numberp x) - (and (numberp y) (= x y))) - ((consp x) - ;; XEmacs change - (while (and (consp x) (consp y) (equalp (cl-pop x) (cl-pop y)))) - (and (not (consp x)) (equalp x y))) - ((vectorp x) - (and (vectorp y) (= (length x) (length y)) - (let ((i (length x))) - (while (and (>= (setq i (1- i)) 0) - (equalp (aref x i) (aref y i)))) - (< i 0)))) - (t (equal x y)))) - - -;;; Control structures. - -(defun cl-mapcar-many (cl-func cl-seqs) - (if (cdr (cdr cl-seqs)) - (let* ((cl-res nil) - (cl-n (apply 'min (mapcar 'length cl-seqs))) - (cl-i 0) - (cl-args (copy-sequence cl-seqs)) - cl-p1 cl-p2) - (setq cl-seqs (copy-sequence cl-seqs)) - (while (< cl-i cl-n) - (setq cl-p1 cl-seqs cl-p2 cl-args) - (while cl-p1 - (setcar cl-p2 - (if (consp (car cl-p1)) - (prog1 (car (car cl-p1)) - (setcar cl-p1 (cdr (car cl-p1)))) - (aref (car cl-p1) cl-i))) - (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2))) - (cl-push (apply cl-func cl-args) cl-res) - (setq cl-i (1+ cl-i))) - (nreverse cl-res)) - (let ((cl-res nil) - (cl-x (car cl-seqs)) - (cl-y (nth 1 cl-seqs))) - (let ((cl-n (min (length cl-x) (length cl-y))) - (cl-i -1)) - (while (< (setq cl-i (1+ cl-i)) cl-n) - (cl-push (funcall cl-func - (if (consp cl-x) (cl-pop cl-x) (aref cl-x cl-i)) - (if (consp cl-y) (cl-pop cl-y) (aref cl-y cl-i))) - cl-res))) - (nreverse cl-res)))) - -(defun map (cl-type cl-func cl-seq &rest cl-rest) - "Map a function across one or more sequences, returning a sequence. -TYPE is the sequence type to return, FUNC is the function, and SEQS -are the argument sequences." - (let ((cl-res (apply 'mapcar* cl-func cl-seq cl-rest))) - (and cl-type (coerce cl-res cl-type)))) - -(defun maplist (cl-func cl-list &rest cl-rest) - "Map FUNC to each sublist of LIST or LISTS. -Like `mapcar', except applies to lists and their cdr's rather than to -the elements themselves." - (if cl-rest - (let ((cl-res nil) - (cl-args (cons cl-list (copy-sequence cl-rest))) - cl-p) - (while (not (memq nil cl-args)) - (cl-push (apply cl-func cl-args) cl-res) - (setq cl-p cl-args) - (while cl-p (setcar cl-p (cdr (cl-pop cl-p)) ))) - (nreverse cl-res)) - (let ((cl-res nil)) - (while cl-list - (cl-push (funcall cl-func cl-list) cl-res) - (setq cl-list (cdr cl-list))) - (nreverse cl-res)))) - - -;; mapc is now in C, renamed from `mapc-internal'. - -;(defun mapc (cl-func cl-seq &rest cl-rest) -; "Like `mapcar', but does not accumulate values returned by the function." -; (if cl-rest -; (apply 'map nil cl-func cl-seq cl-rest) -; ;; XEmacs change: we call mapc-internal, which really doesn't -; ;; accumulate any results. -; (mapc-internal cl-func cl-seq)) -; cl-seq) - -(defun mapl (cl-func cl-list &rest cl-rest) - "Like `maplist', but does not accumulate values returned by the function." - (if cl-rest - (apply 'maplist cl-func cl-list cl-rest) - (let ((cl-p cl-list)) - (while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p))))) - cl-list) - -(defun mapcan (cl-func cl-seq &rest cl-rest) - "Like `mapcar', but nconc's together the values returned by the function." - (apply 'nconc (apply 'mapcar* cl-func cl-seq cl-rest))) - -(defun mapcon (cl-func cl-list &rest cl-rest) - "Like `maplist', but nconc's together the values returned by the function." - (apply 'nconc (apply 'maplist cl-func cl-list cl-rest))) - -(defun some (cl-pred cl-seq &rest cl-rest) - "Return true if PREDICATE is true of any element of SEQ or SEQs. -If so, return the true (non-nil) value returned by PREDICATE." - (if (or cl-rest (nlistp cl-seq)) - (catch 'cl-some - (apply 'map nil - (function (lambda (&rest cl-x) - (let ((cl-res (apply cl-pred cl-x))) - (if cl-res (throw 'cl-some cl-res))))) - cl-seq cl-rest) nil) - (let ((cl-x nil)) - (while (and cl-seq (not (setq cl-x (funcall cl-pred (cl-pop cl-seq)))))) - cl-x))) - -(defun every (cl-pred cl-seq &rest cl-rest) - "Return true if PREDICATE is true of every element of SEQ or SEQs." - (if (or cl-rest (nlistp cl-seq)) - (catch 'cl-every - (apply 'map nil - (function (lambda (&rest cl-x) - (or (apply cl-pred cl-x) (throw 'cl-every nil)))) - cl-seq cl-rest) t) - (while (and cl-seq (funcall cl-pred (car cl-seq))) - (setq cl-seq (cdr cl-seq))) - (null cl-seq))) - -(defun notany (cl-pred cl-seq &rest cl-rest) - "Return true if PREDICATE is false of every element of SEQ or SEQs." - (not (apply 'some cl-pred cl-seq cl-rest))) - -(defun notevery (cl-pred cl-seq &rest cl-rest) - "Return true if PREDICATE is false of some element of SEQ or SEQs." - (not (apply 'every cl-pred cl-seq cl-rest))) - -;;; Support for `loop'. -(defun cl-map-keymap (cl-func cl-map) - (while (symbolp cl-map) (setq cl-map (symbol-function cl-map))) - (if (eq cl-emacs-type 'lucid) (funcall 'map-keymap cl-func cl-map) - (if (listp cl-map) - (let ((cl-p cl-map)) - (while (consp (setq cl-p (cdr cl-p))) - (cond ((consp (car cl-p)) - (funcall cl-func (car (car cl-p)) (cdr (car cl-p)))) - ((vectorp (car cl-p)) - (cl-map-keymap cl-func (car cl-p))) - ((eq (car cl-p) 'keymap) - (setq cl-p nil))))) - (let ((cl-i -1)) - (while (< (setq cl-i (1+ cl-i)) (length cl-map)) - (if (aref cl-map cl-i) - (funcall cl-func cl-i (aref cl-map cl-i)))))))) - -(defun cl-map-keymap-recursively (cl-func-rec cl-map &optional cl-base) - (or cl-base - (setq cl-base (copy-sequence (if (eq cl-emacs-type 18) "0" [0])))) - (cl-map-keymap - (function - (lambda (cl-key cl-bind) - (aset cl-base (1- (length cl-base)) cl-key) - (if (keymapp cl-bind) - (cl-map-keymap-recursively - cl-func-rec cl-bind - (funcall (if (eq cl-emacs-type 18) 'concat 'vconcat) - cl-base (list 0))) - (funcall cl-func-rec cl-base cl-bind)))) - cl-map)) - -(defun cl-map-intervals (cl-func &optional cl-what cl-prop cl-start cl-end) - (or cl-what (setq cl-what (current-buffer))) - (if (bufferp cl-what) - (let (cl-mark cl-mark2 (cl-next t) cl-next2) - (save-excursion - (set-buffer cl-what) - (setq cl-mark (copy-marker (or cl-start (point-min)))) - (setq cl-mark2 (and cl-end (copy-marker cl-end)))) - (while (and cl-next (or (not cl-mark2) (< cl-mark cl-mark2))) - (setq cl-next (and (fboundp 'next-property-change) - (if cl-prop (next-single-property-change - cl-mark cl-prop cl-what) - (next-property-change cl-mark cl-what))) - cl-next2 (or cl-next (save-excursion - (set-buffer cl-what) (point-max)))) - (funcall cl-func (prog1 (marker-position cl-mark) - (set-marker cl-mark cl-next2)) - (if cl-mark2 (min cl-next2 cl-mark2) cl-next2))) - (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil))) - (or cl-start (setq cl-start 0)) - (or cl-end (setq cl-end (length cl-what))) - (while (< cl-start cl-end) - (let ((cl-next (or (and (fboundp 'next-property-change) - (if cl-prop (next-single-property-change - cl-start cl-prop cl-what) - (next-property-change cl-start cl-what))) - cl-end))) - (funcall cl-func cl-start (min cl-next cl-end)) - (setq cl-start cl-next))))) - -(defun cl-map-overlays (cl-func &optional cl-buffer cl-start cl-end cl-arg) - (or cl-buffer (setq cl-buffer (current-buffer))) - (if (fboundp 'overlay-lists) - - ;; This is the preferred algorithm, though overlay-lists is undocumented. - (let (cl-ovl) - (save-excursion - (set-buffer cl-buffer) - (setq cl-ovl (overlay-lists)) - (if cl-start (setq cl-start (copy-marker cl-start))) - (if cl-end (setq cl-end (copy-marker cl-end)))) - (setq cl-ovl (nconc (car cl-ovl) (cdr cl-ovl))) - (while (and cl-ovl - (or (not (overlay-start (car cl-ovl))) - (and cl-end (>= (overlay-start (car cl-ovl)) cl-end)) - (and cl-start (<= (overlay-end (car cl-ovl)) cl-start)) - (not (funcall cl-func (car cl-ovl) cl-arg)))) - (setq cl-ovl (cdr cl-ovl))) - (if cl-start (set-marker cl-start nil)) - (if cl-end (set-marker cl-end nil))) - - ;; This alternate algorithm fails to find zero-length overlays. - (let ((cl-mark (save-excursion (set-buffer cl-buffer) - (copy-marker (or cl-start (point-min))))) - (cl-mark2 (and cl-end (save-excursion (set-buffer cl-buffer) - (copy-marker cl-end)))) - cl-pos cl-ovl) - (while (save-excursion - (and (setq cl-pos (marker-position cl-mark)) - (< cl-pos (or cl-mark2 (point-max))) - (progn - (set-buffer cl-buffer) - (setq cl-ovl (overlays-at cl-pos)) - (set-marker cl-mark (next-overlay-change cl-pos))))) - (while (and cl-ovl - (or (/= (overlay-start (car cl-ovl)) cl-pos) - (not (and (funcall cl-func (car cl-ovl) cl-arg) - (set-marker cl-mark nil))))) - (setq cl-ovl (cdr cl-ovl)))) - (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil))))) - -;;; Support for `setf'. -(defun cl-set-frame-visible-p (frame val) - (cond ((null val) (make-frame-invisible frame)) - ((eq val 'icon) (iconify-frame frame)) - (t (make-frame-visible frame))) - val) - -;;; Support for `progv'. -(defvar cl-progv-save) -(defun cl-progv-before (syms values) - (while syms - (cl-push (if (boundp (car syms)) - (cons (car syms) (symbol-value (car syms))) - (car syms)) cl-progv-save) - (if values - (set (cl-pop syms) (cl-pop values)) - (makunbound (cl-pop syms))))) - -(defun cl-progv-after () - (while cl-progv-save - (if (consp (car cl-progv-save)) - (set (car (car cl-progv-save)) (cdr (car cl-progv-save))) - (makunbound (car cl-progv-save))) - (cl-pop cl-progv-save))) - - -;;; Numbers. - -(defun gcd (&rest args) - "Return the greatest common divisor of the arguments." - (let ((a (abs (or (cl-pop args) 0)))) - (while args - (let ((b (abs (cl-pop args)))) - (while (> b 0) (setq b (% a (setq a b)))))) - a)) - -(defun lcm (&rest args) - "Return the least common multiple of the arguments." - (if (memq 0 args) - 0 - (let ((a (abs (or (cl-pop args) 1)))) - (while args - (let ((b (abs (cl-pop args)))) - (setq a (* (/ a (gcd a b)) b)))) - a))) - -(defun isqrt (a) - "Return the integer square root of the argument." - (if (and (integerp a) (> a 0)) - ;; XEmacs change - (let ((g (cond ((>= a 1000000) 10000) ((>= a 10000) 1000) - ((>= a 100) 100) (t 10))) - g2) - (while (< (setq g2 (/ (+ g (/ a g)) 2)) g) - (setq g g2)) - g) - (if (eq a 0) 0 (signal 'arith-error nil)))) - -(defun cl-expt (x y) - "Return X raised to the power of Y. Works only for integer arguments." - (if (<= y 0) (if (= y 0) 1 (if (memq x '(-1 1)) (cl-expt x (- y)) 0)) - (* (if (= (% y 2) 0) 1 x) (cl-expt (* x x) (/ y 2))))) -(or (and (fboundp 'expt) (subrp (symbol-function 'expt))) - (defalias 'expt 'cl-expt)) - -(defun floor* (x &optional y) - "Return a list of the floor of X and the fractional part of X. -With two arguments, return floor and remainder of their quotient." - (let ((q (floor x y))) - (list q (- x (if y (* y q) q))))) - -(defun ceiling* (x &optional y) - "Return a list of the ceiling of X and the fractional part of X. -With two arguments, return ceiling and remainder of their quotient." - (let ((res (floor* x y))) - (if (= (car (cdr res)) 0) res - (list (1+ (car res)) (- (car (cdr res)) (or y 1)))))) - -(defun truncate* (x &optional y) - "Return a list of the integer part of X and the fractional part of X. -With two arguments, return truncation and remainder of their quotient." - (if (eq (>= x 0) (or (null y) (>= y 0))) - (floor* x y) (ceiling* x y))) - -(defun round* (x &optional y) - "Return a list of X rounded to the nearest integer and the remainder. -With two arguments, return rounding and remainder of their quotient." - (if y - (if (and (integerp x) (integerp y)) - (let* ((hy (/ y 2)) - (res (floor* (+ x hy) y))) - (if (and (= (car (cdr res)) 0) - (= (+ hy hy) y) - (/= (% (car res) 2) 0)) - (list (1- (car res)) hy) - (list (car res) (- (car (cdr res)) hy)))) - (let ((q (round (/ x y)))) - (list q (- x (* q y))))) - (if (integerp x) (list x 0) - (let ((q (round x))) - (list q (- x q)))))) - -(defun mod* (x y) - "The remainder of X divided by Y, with the same sign as Y." - (nth 1 (floor* x y))) - -(defun rem* (x y) - "The remainder of X divided by Y, with the same sign as X." - (nth 1 (truncate* x y))) - -(defun signum (a) - "Return 1 if A is positive, -1 if negative, 0 if zero." - (cond ((> a 0) 1) ((< a 0) -1) (t 0))) - - -;; Random numbers. - -(defvar *random-state*) -(defun random* (lim &optional state) - "Return a random nonnegative number less than LIM, an integer or float. -Optional second arg STATE is a random-state object." - (or state (setq state *random-state*)) - ;; Inspired by "ran3" from Numerical Recipes. Additive congruential method. - (let ((vec (aref state 3))) - (if (integerp vec) - (let ((i 0) (j (- 1357335 (% (abs vec) 1357333))) (k 1) ii) - (aset state 3 (setq vec (make-vector 55 nil))) - (aset vec 0 j) - (while (> (setq i (% (+ i 21) 55)) 0) - (aset vec i (setq j (prog1 k (setq k (- j k)))))) - (while (< (setq i (1+ i)) 200) (random* 2 state)))) - (let* ((i (aset state 1 (% (1+ (aref state 1)) 55))) - (j (aset state 2 (% (1+ (aref state 2)) 55))) - (n (logand 8388607 (aset vec i (- (aref vec i) (aref vec j)))))) - (if (integerp lim) - (if (<= lim 512) (% n lim) - (if (> lim 8388607) (setq n (+ (lsh n 9) (random* 512 state)))) - (let ((mask 1023)) - (while (< mask (1- lim)) (setq mask (1+ (+ mask mask)))) - (if (< (setq n (logand n mask)) lim) n (random* lim state)))) - (* (/ n '8388608e0) lim))))) - -(defun make-random-state (&optional state) - "Return a copy of random-state STATE, or of `*random-state*' if omitted. -If STATE is t, return a new state object seeded from the time of day." - (cond ((null state) (make-random-state *random-state*)) - ((vectorp state) (cl-copy-tree state t)) - ((integerp state) (vector 'cl-random-state-tag -1 30 state)) - (t (make-random-state (cl-random-time))))) - -(defun random-state-p (object) - "Return t if OBJECT is a random-state object." - (and (vectorp object) (= (length object) 4) - (eq (aref object 0) 'cl-random-state-tag))) - - -;; Implementation limits. - -(defun cl-finite-do (func a b) - (condition-case err - (let ((res (funcall func a b))) ; check for IEEE infinity - (and (numberp res) (/= res (/ res 2)) res)) - (arith-error nil))) - -(defvar most-positive-float) -(defvar most-negative-float) -(defvar least-positive-float) -(defvar least-negative-float) -(defvar least-positive-normalized-float) -(defvar least-negative-normalized-float) -(defvar float-epsilon) -(defvar float-negative-epsilon) - -(defun cl-float-limits () - (or most-positive-float (not (numberp '2e1)) - (let ((x '2e0) y z) - ;; Find maximum exponent (first two loops are optimizations) - (while (cl-finite-do '* x x) (setq x (* x x))) - (while (cl-finite-do '* x (/ x 2)) (setq x (* x (/ x 2)))) - (while (cl-finite-do '+ x x) (setq x (+ x x))) - (setq z x y (/ x 2)) - ;; Now fill in 1's in the mantissa. - (while (and (cl-finite-do '+ x y) (/= (+ x y) x)) - (setq x (+ x y) y (/ y 2))) - (setq most-positive-float x - most-negative-float (- x)) - ;; Divide down until mantissa starts rounding. - (setq x (/ x z) y (/ 16 z) x (* x y)) - (while (condition-case err (and (= x (* (/ x 2) 2)) (> (/ y 2) 0)) - (arith-error nil)) - (setq x (/ x 2) y (/ y 2))) - (setq least-positive-normalized-float y - least-negative-normalized-float (- y)) - ;; Divide down until value underflows to zero. - (setq x (/ 1 z) y x) - (while (condition-case err (> (/ x 2) 0) (arith-error nil)) - (setq x (/ x 2))) - (setq least-positive-float x - least-negative-float (- x)) - (setq x '1e0) - (while (/= (+ '1e0 x) '1e0) (setq x (/ x 2))) - (setq float-epsilon (* x 2)) - (setq x '1e0) - (while (/= (- '1e0 x) '1e0) (setq x (/ x 2))) - (setq float-negative-epsilon (* x 2)))) - nil) - - -;;; Sequence functions. - -;XEmacs -- our built-in is more powerful. -;(defun subseq (seq start &optional end) -; "Return the subsequence of SEQ from START to END. -;If END is omitted, it defaults to the length of the sequence. -;If START or END is negative, it counts from the end." -; (if (stringp seq) (substring seq start end) -; (let (len) -; (and end (< end 0) (setq end (+ end (setq len (length seq))))) -; (if (< start 0) (setq start (+ start (or len (setq len (length seq)))))) -; (cond ((listp seq) -; (if (> start 0) (setq seq (nthcdr start seq))) -; (if end -; (let ((res nil)) -; (while (>= (setq end (1- end)) start) -; (cl-push (cl-pop seq) res)) -; (nreverse res)) -; (copy-sequence seq))) -; (t -; (or end (setq end (or len (length seq)))) -; (let ((res (make-vector (max (- end start) 0) nil)) -; (i 0)) -; (while (< start end) -; (aset res i (aref seq start)) -; (setq i (1+ i) start (1+ start))) -; res)))))) - -(defun concatenate (type &rest seqs) - "Concatenate, into a sequence of type TYPE, the argument SEQUENCES." - (cond ((eq type 'vector) (apply 'vconcat seqs)) - ((eq type 'string) (apply 'concat seqs)) - ((eq type 'list) (apply 'append (append seqs '(nil)))) - (t (error "Not a sequence type name: %s" type)))) - - -;;; List functions. - -(defun revappend (x y) - "Equivalent to (append (reverse X) Y)." - (nconc (reverse x) y)) - -(defun nreconc (x y) - "Equivalent to (nconc (nreverse X) Y)." - (nconc (nreverse x) y)) - -(defun list-length (x) - "Return the length of a list. Return nil if list is circular." - (let ((n 0) (fast x) (slow x)) - (while (and (cdr fast) (not (and (eq fast slow) (> n 0)))) - (setq n (+ n 2) fast (cdr (cdr fast)) slow (cdr slow))) - (if fast (if (cdr fast) nil (1+ n)) n))) - -(defun tailp (sublist list) - "Return true if SUBLIST is a tail of LIST." - (while (and (consp list) (not (eq sublist list))) - (setq list (cdr list))) - (if (numberp sublist) (equal sublist list) (eq sublist list))) - -(defun cl-copy-tree (tree &optional vecp) - "Make a copy of TREE. -If TREE is a cons cell, this recursively copies both its car and its cdr. -Contrast to copy-sequence, which copies only along the cdrs. With second -argument VECP, this copies vectors as well as conses." - (if (consp tree) - (let ((p (setq tree (copy-list tree)))) - (while (consp p) - (if (or (consp (car p)) (and vecp (vectorp (car p)))) - (setcar p (cl-copy-tree (car p) vecp))) - (or (listp (cdr p)) (setcdr p (cl-copy-tree (cdr p) vecp))) - (cl-pop p))) - (if (and vecp (vectorp tree)) - (let ((i (length (setq tree (copy-sequence tree))))) - (while (>= (setq i (1- i)) 0) - (aset tree i (cl-copy-tree (aref tree i) vecp)))))) - tree) -(or (and (fboundp 'copy-tree) (subrp (symbol-function 'copy-tree))) - (defalias 'copy-tree 'cl-copy-tree)) - - -;;; Property lists. - -(defun get* (sym tag &optional def) ; See compiler macro in cl-macs.el - "Return the value of SYMBOL's PROPNAME property, or DEFAULT if none." - (or (get sym tag) - (and def - (let ((plist (symbol-plist sym))) - (while (and plist (not (eq (car plist) tag))) - (setq plist (cdr (cdr plist)))) - (if plist (car (cdr plist)) def))))) - -(defun getf (plist tag &optional def) - "Search PROPLIST for property PROPNAME; return its value or DEFAULT. -PROPLIST is a list of the sort returned by `symbol-plist'." - (setplist '--cl-getf-symbol-- plist) - (or (get '--cl-getf-symbol-- tag) - (and def (get* '--cl-getf-symbol-- tag def)))) - -(defun cl-set-getf (plist tag val) - (let ((p plist)) - (while (and p (not (eq (car p) tag))) (setq p (cdr (cdr p)))) - (if p (progn (setcar (cdr p) val) plist) (list* tag val plist)))) - -(defun cl-do-remf (plist tag) - (let ((p (cdr plist))) - (while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p)))) - (and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t)))) - -(defun cl-remprop (sym tag) - "Remove from SYMBOL's plist the property PROP and its value." - (let ((plist (symbol-plist sym))) - (if (and plist (eq tag (car plist))) - (progn (setplist sym (cdr (cdr plist))) t) - (cl-do-remf plist tag)))) -(or (and (fboundp 'remprop) (subrp (symbol-function 'remprop))) - (defalias 'remprop 'cl-remprop)) - - - -;;; Hash tables. - -(defun make-hash-table (&rest cl-keys) - "Make an empty Common Lisp-style hash-table. -If :test is `eq', `eql', or `equal', this can use XEmacs built-in hash-tables. -In Emacs 19, or with a different test, this internally uses a-lists. -Keywords supported: :test :size -The Common Lisp keywords :rehash-size and :rehash-threshold are ignored." - (let ((cl-test (or (car (cdr (memq ':test cl-keys))) 'eql)) - (cl-size (or (car (cdr (memq ':size cl-keys))) 20))) - ;; XEmacs change - (if (and (memq cl-test '(eq eql equal)) (fboundp 'make-hashtable)) - (funcall 'make-hashtable cl-size cl-test) - (list 'cl-hash-table-tag cl-test - (if (> cl-size 1) (make-vector cl-size 0) - (let ((sym (make-symbol "--hashsym--"))) (set sym nil) sym)) - 0)))) - -(defvar cl-lucid-hash-tag - (if (and (fboundp 'make-hashtable) (vectorp (make-hashtable 1))) - (aref (make-hashtable 1) 0) (make-symbol "--cl-hash-tag--"))) - -(defun hash-table-p (x) - "Return t if OBJECT is a hash table." - (or (eq (car-safe x) 'cl-hash-table-tag) - (and (vectorp x) (= (length x) 4) (eq (aref x 0) cl-lucid-hash-tag)) - (and (fboundp 'hashtablep) (funcall 'hashtablep x)))) - -(defun cl-not-hash-table (x &optional y &rest z) - (signal 'wrong-type-argument (list 'hash-table-p (or y x)))) - -(defun cl-hash-lookup (key table) - (or (eq (car-safe table) 'cl-hash-table-tag) (cl-not-hash-table table)) - (let* ((array (nth 2 table)) (test (car (cdr table))) (str key) sym) - (if (symbolp array) (setq str nil sym (symbol-value array)) - (while (or (consp str) (and (vectorp str) (> (length str) 0))) - (setq str (elt str 0))) - (cond ((stringp str) (if (eq test 'equalp) (setq str (downcase str)))) - ((symbolp str) (setq str (symbol-name str))) - ((and (numberp str) (> str -8000000) (< str 8000000)) - (or (integerp str) (setq str (truncate str))) - (setq str (aref ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" - "11" "12" "13" "14" "15"] (logand str 15)))) - (t (setq str "*"))) - (setq sym (symbol-value (intern-soft str array)))) - (list (and sym (cond ((or (eq test 'eq) - (and (eq test 'eql) (not (numberp key)))) - (assq key sym)) - ((memq test '(eql equal)) (assoc key sym)) - (t (assoc* key sym ':test test)))) - sym str))) - -(defvar cl-builtin-gethash - (if (and (fboundp 'gethash) (subrp (symbol-function 'gethash))) - (symbol-function 'gethash) 'cl-not-hash-table)) -(defvar cl-builtin-remhash - (if (and (fboundp 'remhash) (subrp (symbol-function 'remhash))) - (symbol-function 'remhash) 'cl-not-hash-table)) -(defvar cl-builtin-clrhash - (if (and (fboundp 'clrhash) (subrp (symbol-function 'clrhash))) - (symbol-function 'clrhash) 'cl-not-hash-table)) -(defvar cl-builtin-maphash - (if (and (fboundp 'maphash) (subrp (symbol-function 'maphash))) - (symbol-function 'maphash) 'cl-not-hash-table)) - -(defun cl-gethash (key table &optional def) - "Look up KEY in HASH-TABLE; return corresponding value, or DEFAULT." - (if (consp table) - (let ((found (cl-hash-lookup key table))) - (if (car found) (cdr (car found)) def)) - (funcall cl-builtin-gethash key table def))) -(defalias 'gethash 'cl-gethash) - -(defun cl-puthash (key val table) - (if (consp table) - (let ((found (cl-hash-lookup key table))) - (if (car found) (setcdr (car found) val) - (if (nth 2 found) - (progn - (if (> (nth 3 table) (* (length (nth 2 table)) 3)) - (let ((new-table (make-vector (nth 3 table) 0))) - (mapatoms (function - (lambda (sym) - (set (intern (symbol-name sym) new-table) - (symbol-value sym)))) - (nth 2 table)) - (setcar (cdr (cdr table)) new-table))) - (set (intern (nth 2 found) (nth 2 table)) - (cons (cons key val) (nth 1 found)))) - (set (nth 2 table) (cons (cons key val) (nth 1 found)))) - (setcar (cdr (cdr (cdr table))) (1+ (nth 3 table))))) - (funcall 'puthash key val table)) val) - -(defun cl-remhash (key table) - "Remove KEY from HASH-TABLE." - (if (consp table) - (let ((found (cl-hash-lookup key table))) - (and (car found) - (let ((del (delq (car found) (nth 1 found)))) - (setcar (cdr (cdr (cdr table))) (1- (nth 3 table))) - (if (nth 2 found) (set (intern (nth 2 found) (nth 2 table)) del) - (set (nth 2 table) del)) t))) - (prog1 (not (eq (funcall cl-builtin-gethash key table '--cl--) '--cl--)) - (funcall cl-builtin-remhash key table)))) -(defalias 'remhash 'cl-remhash) - -(defun cl-clrhash (table) - "Clear HASH-TABLE." - (if (consp table) - (progn - (or (hash-table-p table) (cl-not-hash-table table)) - (if (symbolp (nth 2 table)) (set (nth 2 table) nil) - (setcar (cdr (cdr table)) (make-vector (length (nth 2 table)) 0))) - (setcar (cdr (cdr (cdr table))) 0)) - (funcall cl-builtin-clrhash table)) - nil) -(defalias 'clrhash 'cl-clrhash) - -(defun cl-maphash (cl-func cl-table) - "Call FUNCTION on keys and values from HASH-TABLE." - (or (hash-table-p cl-table) (cl-not-hash-table cl-table)) - (if (consp cl-table) - (mapatoms (function (lambda (cl-x) - (setq cl-x (symbol-value cl-x)) - (while cl-x - (funcall cl-func (car (car cl-x)) - (cdr (car cl-x))) - (setq cl-x (cdr cl-x))))) - (if (symbolp (nth 2 cl-table)) - (vector (nth 2 cl-table)) (nth 2 cl-table))) - (funcall cl-builtin-maphash cl-func cl-table))) -(defalias 'maphash 'cl-maphash) - -(defun hash-table-count (table) - "Return the number of entries in HASH-TABLE." - (or (hash-table-p table) (cl-not-hash-table table)) - (if (consp table) (nth 3 table) (funcall 'hashtable-fullness table))) - - -;;; Some debugging aids. - -(defun cl-prettyprint (form) - "Insert a pretty-printed rendition of a Lisp FORM in current buffer." - (let ((pt (point)) last) - (insert "\n" (prin1-to-string form) "\n") - (setq last (point)) - (goto-char (1+ pt)) - (while (search-forward "(quote " last t) - (delete-backward-char 7) - (insert "'") - (forward-sexp) - (delete-char 1)) - (goto-char (1+ pt)) - (cl-do-prettyprint))) - -(defun cl-do-prettyprint () - (skip-chars-forward " ") - (if (looking-at "(") - (let ((skip (or (looking-at "((") (looking-at "(prog") - (looking-at "(unwind-protect ") - (looking-at "(function (") - (looking-at "(cl-block-wrapper "))) - (two (or (looking-at "(defun ") (looking-at "(defmacro "))) - (let (or (looking-at "(let\\*? ") (looking-at "(while "))) - (set (looking-at "(p?set[qf] "))) - (if (or skip let - (progn - (forward-sexp) - (and (>= (current-column) 78) (progn (backward-sexp) t)))) - (let ((nl t)) - (forward-char 1) - (cl-do-prettyprint) - (or skip (looking-at ")") (cl-do-prettyprint)) - (or (not two) (looking-at ")") (cl-do-prettyprint)) - (while (not (looking-at ")")) - (if set (setq nl (not nl))) - (if nl (insert "\n")) - (lisp-indent-line) - (cl-do-prettyprint)) - (forward-char 1)))) - (forward-sexp))) - -(defvar cl-macroexpand-cmacs nil) -(defvar cl-closure-vars nil) - -(defun cl-macroexpand-all (form &optional env) - "Expand all macro calls through a Lisp FORM. -This also does some trivial optimizations to make the form prettier." - (while (or (not (eq form (setq form (macroexpand form env)))) - (and cl-macroexpand-cmacs - (not (eq form (setq form (compiler-macroexpand form))))))) - (cond ((not (consp form)) form) - ((memq (car form) '(let let*)) - (if (null (nth 1 form)) - (cl-macroexpand-all (cons 'progn (cddr form)) env) - (let ((letf nil) (res nil) (lets (cadr form))) - (while lets - (cl-push (if (consp (car lets)) - (let ((exp (cl-macroexpand-all (caar lets) env))) - (or (symbolp exp) (setq letf t)) - (cons exp (cl-macroexpand-body (cdar lets) env))) - (let ((exp (cl-macroexpand-all (car lets) env))) - (if (symbolp exp) exp - (setq letf t) (list exp nil)))) res) - (setq lets (cdr lets))) - (list* (if letf (if (eq (car form) 'let) 'letf 'letf*) (car form)) - (nreverse res) (cl-macroexpand-body (cddr form) env))))) - ((eq (car form) 'cond) - (cons (car form) - (mapcar (function (lambda (x) (cl-macroexpand-body x env))) - (cdr form)))) - ((eq (car form) 'condition-case) - (list* (car form) (nth 1 form) (cl-macroexpand-all (nth 2 form) env) - (mapcar (function - (lambda (x) - (cons (car x) (cl-macroexpand-body (cdr x) env)))) - (cdddr form)))) - ((memq (car form) '(quote function)) - (if (eq (car-safe (nth 1 form)) 'lambda) - (let ((body (cl-macroexpand-body (cddadr form) env))) - (if (and cl-closure-vars (eq (car form) 'function) - (cl-expr-contains-any body cl-closure-vars)) - (let* ((new (mapcar 'gensym cl-closure-vars)) - (sub (pairlis cl-closure-vars new)) (decls nil)) - (while (or (stringp (car body)) - (eq (car-safe (car body)) 'interactive)) - (cl-push (list 'quote (cl-pop body)) decls)) - (put (car (last cl-closure-vars)) 'used t) - (append - (list 'list '(quote lambda) '(quote (&rest --cl-rest--))) - (sublis sub (nreverse decls)) - (list - (list* 'list '(quote apply) - (list 'list '(quote quote) - (list 'function - (list* 'lambda - (append new (cadadr form)) - (sublis sub body)))) - (nconc (mapcar (function - (lambda (x) - (list 'list '(quote quote) x))) - cl-closure-vars) - '((quote --cl-rest--))))))) - (list (car form) (list* 'lambda (cadadr form) body)))) - (let ((found (assq (cadr form) env))) - (if (eq (cadr (caddr found)) 'cl-labels-args) - (cl-macroexpand-all (cadr (caddr (cadddr found))) env) - form)))) - ((memq (car form) '(defun defmacro)) - (list* (car form) (nth 1 form) (cl-macroexpand-body (cddr form) env))) - ((and (eq (car form) 'progn) (not (cddr form))) - (cl-macroexpand-all (nth 1 form) env)) - ((eq (car form) 'setq) - (let* ((args (cl-macroexpand-body (cdr form) env)) (p args)) - (while (and p (symbolp (car p))) (setq p (cddr p))) - (if p (cl-macroexpand-all (cons 'setf args)) (cons 'setq args)))) - (t (cons (car form) (cl-macroexpand-body (cdr form) env))))) - -(defun cl-macroexpand-body (body &optional env) - (mapcar (function (lambda (x) (cl-macroexpand-all x env))) body)) - -(defun cl-prettyexpand (form &optional full) - (message "Expanding...") - (let ((cl-macroexpand-cmacs full) (cl-compiling-file full) - (byte-compile-macro-environment nil)) - (setq form (cl-macroexpand-all form - (and (not full) '((block) (eval-when))))) - (message "Formatting...") - (prog1 (cl-prettyprint form) - (message "")))) - - - -(run-hooks 'cl-extra-load-hook) - -(provide 'cl-extra) - -;;; cl-extra.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl/cl-macs.el --- a/lisp/cl/cl-macs.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2761 +0,0 @@ -;;; cl-macs.el --- Common Lisp extensions for GNU Emacs Lisp (part four) - -;; Copyright (C) 1993 Free Software Foundation, Inc. - -;; Author: Dave Gillespie -;; Version: 2.02 -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; These are extensions to Emacs Lisp that provide a degree of -;; Common Lisp compatibility, beyond what is already built-in -;; in Emacs Lisp. -;; -;; This package was written by Dave Gillespie; it is a complete -;; rewrite of Cesar Quiroz's original cl.el package of December 1986. -;; -;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. -;; -;; Bug reports, comments, and suggestions are welcome! - -;; This file contains the portions of the Common Lisp extensions -;; package which should be autoloaded, but need only be present -;; if the compiler or interpreter is used---this file is not -;; necessary for executing compiled code. - -;; See cl.el for Change Log. - - -;;; Code: - -(or (memq 'cl-19 features) - (error "Tried to load `cl-macs' before `cl'!")) - - -;;; We define these here so that this file can compile without having -;;; loaded the cl.el file already. - -(defmacro cl-push (x place) (list 'setq place (list 'cons x place))) -(defmacro cl-pop (place) - (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) -(defmacro cl-pop2 (place) - (list 'prog1 (list 'car (list 'cdr place)) - (list 'setq place (list 'cdr (list 'cdr place))))) -(put 'cl-push 'edebug-form-spec 'edebug-sexps) -(put 'cl-pop 'edebug-form-spec 'edebug-sexps) -(put 'cl-pop2 'edebug-form-spec 'edebug-sexps) - -(defvar cl-emacs-type) -(defvar cl-optimize-safety) -(defvar cl-optimize-speed) - - -;;; This kludge allows macros which use cl-transform-function-property -;;; to be called at compile-time. - -(require - (progn - (or (fboundp 'defalias) (fset 'defalias 'fset)) - (or (fboundp 'cl-transform-function-property) - (defalias 'cl-transform-function-property - (function (lambda (n p f) - (list 'put (list 'quote n) (list 'quote p) - (list 'function (cons 'lambda f))))))) - (car (or features (setq features (list 'cl-kludge)))))) - - -;;; Initialization. - -(defvar cl-old-bc-file-form nil) - -;; Patch broken Emacs 18 compiler (re top-level macros). -;; Emacs 19 compiler doesn't need this patch. -;; Also, undo broken definition of `eql' that uses same bytecode as `eq'. - -;;;###autoload -(defun cl-compile-time-init () - (setq cl-old-bc-file-form (symbol-function 'byte-compile-file-form)) - (or (fboundp 'byte-compile-flush-pending) ; Emacs 19 compiler? - (defalias 'byte-compile-file-form - (function - (lambda (form) - (setq form (macroexpand form byte-compile-macro-environment)) - (if (eq (car-safe form) 'progn) - (cons 'progn (mapcar 'byte-compile-file-form (cdr form))) - (funcall cl-old-bc-file-form form)))))) - (put 'eql 'byte-compile 'cl-byte-compile-compiler-macro) - (run-hooks 'cl-hack-bytecomp-hook)) - - -;;; Symbols. - -(defvar *gensym-counter*) - -;;;###autoload -(defun gensym (&optional arg) - "Generate a new uninterned symbol. -The name is made by appending a number to PREFIX, default \"G\"." - (let ((prefix (if (stringp arg) arg "G")) - (num (if (integerp arg) arg - (prog1 *gensym-counter* - (setq *gensym-counter* (1+ *gensym-counter*)))))) - (make-symbol (format "%s%d" prefix num)))) - -;;;###autoload -(defun gentemp (&optional arg) - "Generate a new interned symbol with a unique name. -The name is made by appending a number to PREFIX, default \"G\"." - (let ((prefix (if (stringp arg) arg "G")) - name) - (while (intern-soft (setq name (format "%s%d" prefix *gensym-counter*))) - (setq *gensym-counter* (1+ *gensym-counter*))) - (intern name))) - - -;;; Program structure. - -;;;###autoload -(defmacro defun* (name args &rest body) - "(defun* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. -Like normal `defun', except ARGLIST allows full Common Lisp conventions, -and BODY is implicitly surrounded by (block NAME ...)." - (let* ((res (cl-transform-lambda (cons args body) name)) - (form (list* 'defun name (cdr res)))) - (if (car res) (list 'progn (car res) form) form))) - -;;;###autoload -(defmacro defmacro* (name args &rest body) - "(defmacro* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a macro. -Like normal `defmacro', except ARGLIST allows full Common Lisp conventions, -and BODY is implicitly surrounded by (block NAME ...)." - (let* ((res (cl-transform-lambda (cons args body) name)) - (form (list* 'defmacro name (cdr res)))) - (if (car res) (list 'progn (car res) form) form))) - -;;;###autoload -(defmacro function* (func) - "(function* SYMBOL-OR-LAMBDA): introduce a function. -Like normal `function', except that if argument is a lambda form, its -ARGLIST allows full Common Lisp conventions." - (if (eq (car-safe func) 'lambda) - (let* ((res (cl-transform-lambda (cdr func) 'cl-none)) - (form (list 'function (cons 'lambda (cdr res))))) - (if (car res) (list 'progn (car res) form) form)) - (list 'function func))) - -(defun cl-transform-function-property (func prop form) - (let ((res (cl-transform-lambda form func))) - (append '(progn) (cdr (cdr (car res))) - (list (list 'put (list 'quote func) (list 'quote prop) - (list 'function (cons 'lambda (cdr res)))))))) - -(defconst lambda-list-keywords - '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) - -(defvar cl-macro-environment nil) -(defvar bind-block) (defvar bind-defs) (defvar bind-enquote) -(defvar bind-inits) (defvar bind-lets) (defvar bind-forms) - -(defun cl-transform-lambda (form bind-block) - (let* ((args (car form)) (body (cdr form)) - (bind-defs nil) (bind-enquote nil) - (bind-inits nil) (bind-lets nil) (bind-forms nil) - (header nil) (simple-args nil)) - (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) - (cl-push (cl-pop body) header)) - (setq args (if (listp args) (copy-list args) (list '&rest args))) - (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) - (if (setq bind-defs (cadr (memq '&cl-defs args))) - (setq args (delq '&cl-defs (delq bind-defs args)) - bind-defs (cadr bind-defs))) - (if (setq bind-enquote (memq '&cl-quote args)) - (setq args (delq '&cl-quote args))) - (if (memq '&whole args) (error "&whole not currently implemented")) - (let* ((p (memq '&environment args)) (v (cadr p))) - (if p (setq args (nconc (delq (car p) (delq v args)) - (list '&aux (list v 'cl-macro-environment)))))) - (while (and args (symbolp (car args)) - (not (memq (car args) '(nil &rest &body &key &aux))) - (not (and (eq (car args) '&optional) - (or bind-defs (consp (cadr args)))))) - (cl-push (cl-pop args) simple-args)) - (or (eq bind-block 'cl-none) - (setq body (list (list* 'block bind-block body)))) - (if (null args) - (list* nil (nreverse simple-args) (nconc (nreverse header) body)) - (if (memq '&optional simple-args) (cl-push '&optional args)) - (cl-do-arglist args nil (- (length simple-args) - (if (memq '&optional simple-args) 1 0))) - (setq bind-lets (nreverse bind-lets)) - (list* (and bind-inits (list* 'eval-when '(compile load eval) - (nreverse bind-inits))) - (nconc (nreverse simple-args) - (list '&rest (car (cl-pop bind-lets)))) - (nconc (nreverse header) - (list (nconc (list 'let* bind-lets) - (nreverse bind-forms) body))))))) - -(defun cl-do-arglist (args expr &optional num) ; uses bind-* - (if (nlistp args) - (if (or (memq args lambda-list-keywords) (not (symbolp args))) - (error "Invalid argument name: %s" args) - (cl-push (list args expr) bind-lets)) - (setq args (copy-list args)) - (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) - (let ((p (memq '&body args))) (if p (setcar p '&rest))) - (if (memq '&environment args) (error "&environment used incorrectly")) - (let ((save-args args) - (restarg (memq '&rest args)) - (safety (if (cl-compiling-file) cl-optimize-safety 3)) - (keys nil) - (laterarg nil) (exactarg nil) minarg) - (or num (setq num 0)) - (if (listp (cadr restarg)) - (setq restarg (gensym "--rest--")) - (setq restarg (cadr restarg))) - (cl-push (list restarg expr) bind-lets) - (if (eq (car args) '&whole) - (cl-push (list (cl-pop2 args) restarg) bind-lets)) - (let ((p args)) - (setq minarg restarg) - (while (and p (not (memq (car p) lambda-list-keywords))) - (or (eq p args) (setq minarg (list 'cdr minarg))) - (setq p (cdr p))) - (if (memq (car p) '(nil &aux)) - (setq minarg (list '= (list 'length restarg) - (length (ldiff args p))) - exactarg (not (eq args p))))) - (while (and args (not (memq (car args) lambda-list-keywords))) - (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car) - restarg))) - (cl-do-arglist - (cl-pop args) - (if (or laterarg (= safety 0)) poparg - (list 'if minarg poparg - (list 'signal '(quote wrong-number-of-arguments) - (list 'list (and (not (eq bind-block 'cl-none)) - (list 'quote bind-block)) - (list 'length restarg))))))) - (setq num (1+ num) laterarg t)) - (while (and (eq (car args) '&optional) (cl-pop args)) - (while (and args (not (memq (car args) lambda-list-keywords))) - (let ((arg (cl-pop args))) - (or (consp arg) (setq arg (list arg))) - (if (cddr arg) (cl-do-arglist (nth 2 arg) (list 'and restarg t))) - (let ((def (if (cdr arg) (nth 1 arg) - (or (car bind-defs) - (nth 1 (assq (car arg) bind-defs))))) - (poparg (list 'pop restarg))) - (and def bind-enquote (setq def (list 'quote def))) - (cl-do-arglist (car arg) - (if def (list 'if restarg poparg def) poparg)) - (setq num (1+ num)))))) - (if (eq (car args) '&rest) - (let ((arg (cl-pop2 args))) - (if (consp arg) (cl-do-arglist arg restarg))) - (or (eq (car args) '&key) (= safety 0) exactarg - (cl-push (list 'if restarg - (list 'signal '(quote wrong-number-of-arguments) - (list 'list - (and (not (eq bind-block 'cl-none)) - (list 'quote bind-block)) - (list '+ num (list 'length restarg))))) - bind-forms))) - (while (and (eq (car args) '&key) (cl-pop args)) - (while (and args (not (memq (car args) lambda-list-keywords))) - (let ((arg (cl-pop args))) - (or (consp arg) (setq arg (list arg))) - (let* ((karg (if (consp (car arg)) (caar arg) - (intern (format ":%s" (car arg))))) - (varg (if (consp (car arg)) (cadar arg) (car arg))) - (def (if (cdr arg) (cadr arg) - (or (car bind-defs) (cadr (assq varg bind-defs))))) - (look (list 'memq (list 'quote karg) restarg))) - (and def bind-enquote (setq def (list 'quote def))) - (if (cddr arg) - (let* ((temp (or (nth 2 arg) (gensym))) - (val (list 'car (list 'cdr temp)))) - (cl-do-arglist temp look) - (cl-do-arglist varg - (list 'if temp - (list 'prog1 val (list 'setq temp t)) - def))) - (cl-do-arglist - varg - (list 'car - (list 'cdr - (if (null def) - look - (list 'or look - (if (eq (cl-const-expr-p def) t) - (list - 'quote - (list nil (cl-const-expr-val def))) - (list 'list nil def)))))))) - (cl-push karg keys) - (if (= (aref (symbol-name karg) 0) ?:) - (progn (set karg karg) - (cl-push (list 'setq karg (list 'quote karg)) - bind-inits))))))) - (setq keys (nreverse keys)) - (or (and (eq (car args) '&allow-other-keys) (cl-pop args)) - (null keys) (= safety 0) - (let* ((var (gensym "--keys--")) - (allow '(:allow-other-keys)) - (check (list - 'while var - (list - 'cond - (list (list 'memq (list 'car var) - (list 'quote (append keys allow))) - (list 'setq var (list 'cdr (list 'cdr var)))) - (list (list 'car - (list 'cdr - (list 'memq (cons 'quote allow) - restarg))) - (list 'setq var nil)) - (list t - (list - 'error - (format "Keyword argument %%s not one of %s" - keys) - (list 'car var))))))) - (cl-push (list 'let (list (list var restarg)) check) bind-forms))) - (while (and (eq (car args) '&aux) (cl-pop args)) - (while (and args (not (memq (car args) lambda-list-keywords))) - (if (consp (car args)) - (if (and bind-enquote (cadar args)) - (cl-do-arglist (caar args) - (list 'quote (cadr (cl-pop args)))) - (cl-do-arglist (caar args) (cadr (cl-pop args)))) - (cl-do-arglist (cl-pop args) nil)))) - (if args (error "Malformed argument list %s" save-args))))) - -(defun cl-arglist-args (args) - (if (nlistp args) (list args) - (let ((res nil) (kind nil) arg) - (while (consp args) - (setq arg (cl-pop args)) - (if (memq arg lambda-list-keywords) (setq kind arg) - (if (eq arg '&cl-defs) (cl-pop args) - (and (consp arg) kind (setq arg (car arg))) - (and (consp arg) (cdr arg) (eq kind '&key) (setq arg (cadr arg))) - (setq res (nconc res (cl-arglist-args arg)))))) - (nconc res (and args (list args)))))) - -;;;###autoload -(defmacro destructuring-bind (args expr &rest body) - (let* ((bind-lets nil) (bind-forms nil) (bind-inits nil) - (bind-defs nil) (bind-block 'cl-none)) - (cl-do-arglist (or args '(&aux)) expr) - (append '(progn) bind-inits - (list (nconc (list 'let* (nreverse bind-lets)) - (nreverse bind-forms) body))))) - - -;;; The `eval-when' form. - -(defvar cl-not-toplevel nil) - -;;;###autoload -(defmacro eval-when (when &rest body) - "(eval-when (WHEN...) BODY...): control when BODY is evaluated. -If `compile' is in WHEN, BODY is evaluated when compiled at top-level. -If `load' is in WHEN, BODY is evaluated when loaded after top-level compile. -If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level." - (if (and (fboundp 'cl-compiling-file) (cl-compiling-file) - (not cl-not-toplevel) (not (boundp 'for-effect))) ; horrible kludge - (let ((comp (or (memq 'compile when) (memq ':compile-toplevel when))) - (cl-not-toplevel t)) - (if (or (memq 'load when) (memq ':load-toplevel when)) - (if comp (cons 'progn (mapcar 'cl-compile-time-too body)) - (list* 'if nil nil body)) - (progn (if comp (eval (cons 'progn body))) nil))) - (and (or (memq 'eval when) (memq ':execute when)) - (cons 'progn body)))) - -(defun cl-compile-time-too (form) - (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler)) - (setq form (macroexpand - form (cons '(eval-when) byte-compile-macro-environment)))) - (cond ((eq (car-safe form) 'progn) - (cons 'progn (mapcar 'cl-compile-time-too (cdr form)))) - ((eq (car-safe form) 'eval-when) - (let ((when (nth 1 form))) - (if (or (memq 'eval when) (memq ':execute when)) - (list* 'eval-when (cons 'compile when) (cddr form)) - form))) - (t (eval form) form))) - -(or (and (fboundp 'eval-when-compile) - (not (eq (car-safe (symbol-function 'eval-when-compile)) 'autoload))) - (eval '(defmacro eval-when-compile (&rest body) - "Like `progn', but evaluates the body at compile time. -The result of the body appears to the compiler as a quoted constant." - (list 'quote (eval (cons 'progn body)))))) - -;;;###autoload -(defmacro load-time-value (form &optional read-only) - "Like `progn', but evaluates the body at load time. -The result of the body appears to the compiler as a quoted constant." - (if (cl-compiling-file) - (let* ((temp (gentemp "--cl-load-time--")) - (set (list 'set (list 'quote temp) form))) - (if (and (fboundp 'byte-compile-file-form-defmumble) - (boundp 'this-kind) (boundp 'that-one)) - (fset 'byte-compile-file-form - (list 'lambda '(form) - (list 'fset '(quote byte-compile-file-form) - (list 'quote - (symbol-function 'byte-compile-file-form))) - (list 'byte-compile-file-form (list 'quote set)) - '(byte-compile-file-form form))) - ;; XEmacs change - (print set (symbol-value ;;'outbuffer - 'byte-compile-output-buffer - ))) - (list 'symbol-value (list 'quote temp))) - (list 'quote (eval form)))) - - -;;; Conditional control structures. - -;;;###autoload -(defmacro case (expr &rest clauses) - "(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. -Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared -against each key in each KEYLIST; the corresponding BODY is evaluated. -If no clause succeeds, case returns nil. A single atom may be used in -place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is -allowed only in the final clause, and matches if no other keys match. -Key values are compared by `eql'." - (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) - (head-list nil) - (body (cons - 'cond - (mapcar - (function - (lambda (c) - (cons (cond ((memq (car c) '(t otherwise)) t) - ((eq (car c) 'ecase-error-flag) - (list 'error "ecase failed: %s, %s" - temp (list 'quote (reverse head-list)))) - ((listp (car c)) - (setq head-list (append (car c) head-list)) - (list 'member* temp (list 'quote (car c)))) - (t - (if (memq (car c) head-list) - (error "Duplicate key in case: %s" - (car c))) - (cl-push (car c) head-list) - (list 'eql temp (list 'quote (car c))))) - (or (cdr c) '(nil))))) - clauses)))) - (if (eq temp expr) body - (list 'let (list (list temp expr)) body)))) - -;;;###autoload -(defmacro ecase (expr &rest clauses) - "(ecase EXPR CLAUSES...): like `case', but error if no case fits. -`otherwise'-clauses are not allowed." - (list* 'case expr (append clauses '((ecase-error-flag))))) - -;;;###autoload -(defmacro typecase (expr &rest clauses) - "(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. -Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it -satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, -typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the -final clause, and matches if no other keys match." - (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) - (type-list nil) - (body (cons - 'cond - (mapcar - (function - (lambda (c) - (cons (cond ((eq (car c) 'otherwise) t) - ((eq (car c) 'ecase-error-flag) - (list 'error "etypecase failed: %s, %s" - temp (list 'quote (reverse type-list)))) - (t - (cl-push (car c) type-list) - (cl-make-type-test temp (car c)))) - (or (cdr c) '(nil))))) - clauses)))) - (if (eq temp expr) body - (list 'let (list (list temp expr)) body)))) - -;;;###autoload -(defmacro etypecase (expr &rest clauses) - "(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits. -`otherwise'-clauses are not allowed." - (list* 'typecase expr (append clauses '((ecase-error-flag))))) - - -;;; Blocks and exits. - -;;;###autoload -(defmacro block (name &rest body) - "(block NAME BODY...): define a lexically-scoped block named NAME. -NAME may be any symbol. Code inside the BODY forms can call `return-from' -to jump prematurely out of the block. This differs from `catch' and `throw' -in two respects: First, the NAME is an unevaluated symbol rather than a -quoted symbol or other form; and second, NAME is lexically rather than -dynamically scoped: Only references to it within BODY will work. These -references may appear inside macro expansions, but not inside functions -called from BODY." - (if (cl-safe-expr-p (cons 'progn body)) (cons 'progn body) - (list 'cl-block-wrapper - (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name))) - body)))) - -(defvar cl-active-block-names nil) - -(put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block) -(defun cl-byte-compile-block (cl-form) - (if (fboundp 'byte-compile-form-do-effect) ; Check for optimizing compiler - (progn - (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil)) - (cl-active-block-names (cons cl-entry cl-active-block-names)) - (cl-body (byte-compile-top-level - (cons 'progn (cddr (nth 1 cl-form)))))) - (if (cdr cl-entry) - (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) cl-body)) - (byte-compile-form cl-body)))) - (byte-compile-form (nth 1 cl-form)))) - -(put 'cl-block-throw 'byte-compile 'cl-byte-compile-throw) -(defun cl-byte-compile-throw (cl-form) - (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names))) - (if cl-found (setcdr cl-found t))) - (byte-compile-normal-call (cons 'throw (cdr cl-form)))) - -;;;###autoload -(defmacro return (&optional res) - "(return [RESULT]): return from the block named nil. -This is equivalent to `(return-from nil RESULT)'." - (list 'return-from nil res)) - -;;;###autoload -(defmacro return-from (name &optional res) - "(return-from NAME [RESULT]): return from the block named NAME. -This jump out to the innermost enclosing `(block NAME ...)' form, -returning RESULT from that form (or nil if RESULT is omitted). -This is compatible with Common Lisp, but note that `defun' and -`defmacro' do not create implicit blocks as they do in Common Lisp." - (let ((name2 (intern (format "--cl-block-%s--" name)))) - (list 'cl-block-throw (list 'quote name2) res))) - - -;;; The "loop" macro. - -(defvar args) (defvar loop-accum-var) (defvar loop-accum-vars) -(defvar loop-bindings) (defvar loop-body) (defvar loop-destr-temps) -(defvar loop-finally) (defvar loop-finish-flag) (defvar loop-first-flag) -(defvar loop-initially) (defvar loop-map-form) (defvar loop-name) -(defvar loop-result) (defvar loop-result-explicit) -(defvar loop-result-var) (defvar loop-steps) (defvar loop-symbol-macs) - -;;;###autoload -(defmacro loop (&rest args) - "(loop CLAUSE...): The Common Lisp `loop' macro. -Valid clauses are: - for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, - for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, - for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, - always COND, never COND, thereis COND, collect EXPR into VAR, - append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, - count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, - if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], - unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], - do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, - finally return EXPR, named NAME." - (if (not (memq t (mapcar 'symbolp (delq nil (delq t (copy-list args)))))) - (list 'block nil (list* 'while t args)) - (let ((loop-name nil) (loop-bindings nil) - (loop-body nil) (loop-steps nil) - (loop-result nil) (loop-result-explicit nil) - (loop-result-var nil) (loop-finish-flag nil) - (loop-accum-var nil) (loop-accum-vars nil) - (loop-initially nil) (loop-finally nil) - (loop-map-form nil) (loop-first-flag nil) - (loop-destr-temps nil) (loop-symbol-macs nil)) - (setq args (append args '(cl-end-loop))) - (while (not (eq (car args) 'cl-end-loop)) (cl-parse-loop-clause)) - (if loop-finish-flag - (cl-push (list (list loop-finish-flag t)) loop-bindings)) - (if loop-first-flag - (progn (cl-push (list (list loop-first-flag t)) loop-bindings) - (cl-push (list 'setq loop-first-flag nil) loop-steps))) - (let* ((epilogue (nconc (nreverse loop-finally) - (list (or loop-result-explicit loop-result)))) - (ands (cl-loop-build-ands (nreverse loop-body))) - (while-body (nconc (cadr ands) (nreverse loop-steps))) - (body (append - (nreverse loop-initially) - (list (if loop-map-form - (list 'block '--cl-finish-- - (subst - (if (eq (car ands) t) while-body - (cons (list 'or (car ands) - '(return-from --cl-finish-- - nil)) - while-body)) - '--cl-map loop-map-form)) - (list* 'while (car ands) while-body))) - (if loop-finish-flag - (if (equal epilogue '(nil)) (list loop-result-var) - (list (list 'if loop-finish-flag - (cons 'progn epilogue) loop-result-var))) - epilogue)))) - (if loop-result-var (cl-push (list loop-result-var) loop-bindings)) - (while loop-bindings - (if (cdar loop-bindings) - (setq body (list (cl-loop-let (cl-pop loop-bindings) body t))) - (let ((lets nil)) - (while (and loop-bindings - (not (cdar loop-bindings))) - (cl-push (car (cl-pop loop-bindings)) lets)) - (setq body (list (cl-loop-let lets body nil)))))) - (if loop-symbol-macs - (setq body (list (list* 'symbol-macrolet loop-symbol-macs body)))) - (list* 'block loop-name body))))) - -(defun cl-parse-loop-clause () ; uses args, loop-* - (let ((word (cl-pop args)) - (hash-types '(hash-key hash-keys hash-value hash-values)) - (key-types '(key-code key-codes key-seq key-seqs - key-binding key-bindings))) - (cond - - ((null args) - (error "Malformed `loop' macro")) - - ((eq word 'named) - (setq loop-name (cl-pop args))) - - ((eq word 'initially) - (if (memq (car args) '(do doing)) (cl-pop args)) - (or (consp (car args)) (error "Syntax error on `initially' clause")) - (while (consp (car args)) - (cl-push (cl-pop args) loop-initially))) - - ((eq word 'finally) - (if (eq (car args) 'return) - (setq loop-result-explicit (or (cl-pop2 args) '(quote nil))) - (if (memq (car args) '(do doing)) (cl-pop args)) - (or (consp (car args)) (error "Syntax error on `finally' clause")) - (if (and (eq (caar args) 'return) (null loop-name)) - (setq loop-result-explicit (or (nth 1 (cl-pop args)) '(quote nil))) - (while (consp (car args)) - (cl-push (cl-pop args) loop-finally))))) - - ((memq word '(for as)) - (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil) - (ands nil)) - (while - (let ((var (or (cl-pop args) (gensym)))) - (setq word (cl-pop args)) - (if (eq word 'being) (setq word (cl-pop args))) - (if (memq word '(the each)) (setq word (cl-pop args))) - (if (memq word '(buffer buffers)) - (setq word 'in args (cons '(buffer-list) args))) - (cond - - ((memq word '(from downfrom upfrom to downto upto - above below by)) - (cl-push word args) - (if (memq (car args) '(downto above)) - (error "Must specify `from' value for downward loop")) - (let* ((down (or (eq (car args) 'downfrom) - (memq (caddr args) '(downto above)))) - (excl (or (memq (car args) '(above below)) - (memq (caddr args) '(above below)))) - (start (and (memq (car args) '(from upfrom downfrom)) - (cl-pop2 args))) - (end (and (memq (car args) - '(to upto downto above below)) - (cl-pop2 args))) - (step (and (eq (car args) 'by) (cl-pop2 args))) - (end-var (and (not (cl-const-expr-p end)) (gensym))) - (step-var (and (not (cl-const-expr-p step)) - (gensym)))) - (and step (numberp step) (<= step 0) - (error "Loop `by' value is not positive: %s" step)) - (cl-push (list var (or start 0)) loop-for-bindings) - (if end-var (cl-push (list end-var end) loop-for-bindings)) - (if step-var (cl-push (list step-var step) - loop-for-bindings)) - (if end - (cl-push (list - (if down (if excl '> '>=) (if excl '< '<=)) - var (or end-var end)) loop-body)) - (cl-push (list var (list (if down '- '+) var - (or step-var step 1))) - loop-for-steps))) - - ((memq word '(in in-ref on)) - (let* ((on (eq word 'on)) - (temp (if (and on (symbolp var)) var (gensym)))) - (cl-push (list temp (cl-pop args)) loop-for-bindings) - (cl-push (list 'consp temp) loop-body) - (if (eq word 'in-ref) - (cl-push (list var (list 'car temp)) loop-symbol-macs) - (or (eq temp var) - (progn - (cl-push (list var nil) loop-for-bindings) - (cl-push (list var (if on temp (list 'car temp))) - loop-for-sets)))) - (cl-push (list temp - (if (eq (car args) 'by) - (let ((step (cl-pop2 args))) - (if (and (memq (car-safe step) - '(quote function - function*)) - (symbolp (nth 1 step))) - (list (nth 1 step) temp) - (list 'funcall step temp))) - (list 'cdr temp))) - loop-for-steps))) - - ((eq word '=) - (let* ((start (cl-pop args)) - (then (if (eq (car args) 'then) (cl-pop2 args) start))) - (cl-push (list var nil) loop-for-bindings) - (if (or ands (eq (car args) 'and)) - (progn - (cl-push (list var - (list 'if - (or loop-first-flag - (setq loop-first-flag - (gensym))) - start var)) - loop-for-sets) - (cl-push (list var then) loop-for-steps)) - (cl-push (list var - (if (eq start then) start - (list 'if - (or loop-first-flag - (setq loop-first-flag (gensym))) - start then))) - loop-for-sets)))) - - ((memq word '(across across-ref)) - (let ((temp-vec (gensym)) (temp-idx (gensym))) - (cl-push (list temp-vec (cl-pop args)) loop-for-bindings) - (cl-push (list temp-idx -1) loop-for-bindings) - (cl-push (list '< (list 'setq temp-idx (list '1+ temp-idx)) - (list 'length temp-vec)) loop-body) - (if (eq word 'across-ref) - (cl-push (list var (list 'aref temp-vec temp-idx)) - loop-symbol-macs) - (cl-push (list var nil) loop-for-bindings) - (cl-push (list var (list 'aref temp-vec temp-idx)) - loop-for-sets)))) - - ((memq word '(element elements)) - (let ((ref (or (memq (car args) '(in-ref of-ref)) - (and (not (memq (car args) '(in of))) - (error "Expected `of'")))) - (seq (cl-pop2 args)) - (temp-seq (gensym)) - (temp-idx (if (eq (car args) 'using) - (if (and (= (length (cadr args)) 2) - (eq (caadr args) 'index)) - (cadr (cl-pop2 args)) - (error "Bad `using' clause")) - (gensym)))) - (cl-push (list temp-seq seq) loop-for-bindings) - (cl-push (list temp-idx 0) loop-for-bindings) - (if ref - (let ((temp-len (gensym))) - (cl-push (list temp-len (list 'length temp-seq)) - loop-for-bindings) - (cl-push (list var (list 'elt temp-seq temp-idx)) - loop-symbol-macs) - (cl-push (list '< temp-idx temp-len) loop-body)) - (cl-push (list var nil) loop-for-bindings) - (cl-push (list 'and temp-seq - (list 'or (list 'consp temp-seq) - (list '< temp-idx - (list 'length temp-seq)))) - loop-body) - (cl-push (list var (list 'if (list 'consp temp-seq) - (list 'pop temp-seq) - (list 'aref temp-seq temp-idx))) - loop-for-sets)) - (cl-push (list temp-idx (list '1+ temp-idx)) - loop-for-steps))) - - ((memq word hash-types) - (or (memq (car args) '(in of)) (error "Expected `of'")) - (let* ((table (cl-pop2 args)) - (other (if (eq (car args) 'using) - (if (and (= (length (cadr args)) 2) - (memq (caadr args) hash-types) - (not (eq (caadr args) word))) - (cadr (cl-pop2 args)) - (error "Bad `using' clause")) - (gensym)))) - (if (memq word '(hash-value hash-values)) - (setq var (prog1 other (setq other var)))) - (setq loop-map-form - (list 'maphash (list 'function - (list* 'lambda (list var other) - '--cl-map)) table)))) - - ((memq word '(symbol present-symbol external-symbol - symbols present-symbols external-symbols)) - (let ((ob (and (memq (car args) '(in of)) (cl-pop2 args)))) - (setq loop-map-form - (list 'mapatoms (list 'function - (list* 'lambda (list var) - '--cl-map)) ob)))) - - ((memq word '(overlay overlays extent extents)) - (let ((buf nil) (from nil) (to nil)) - (while (memq (car args) '(in of from to)) - (cond ((eq (car args) 'from) (setq from (cl-pop2 args))) - ((eq (car args) 'to) (setq to (cl-pop2 args))) - (t (setq buf (cl-pop2 args))))) - (setq loop-map-form - (list 'cl-map-extents - (list 'function (list 'lambda (list var (gensym)) - '(progn . --cl-map) nil)) - buf from to)))) - - ((memq word '(interval intervals)) - (let ((buf nil) (prop nil) (from nil) (to nil) - (var1 (gensym)) (var2 (gensym))) - (while (memq (car args) '(in of property from to)) - (cond ((eq (car args) 'from) (setq from (cl-pop2 args))) - ((eq (car args) 'to) (setq to (cl-pop2 args))) - ((eq (car args) 'property) - (setq prop (cl-pop2 args))) - (t (setq buf (cl-pop2 args))))) - (if (and (consp var) (symbolp (car var)) (symbolp (cdr var))) - (setq var1 (car var) var2 (cdr var)) - (cl-push (list var (list 'cons var1 var2)) loop-for-sets)) - (setq loop-map-form - (list 'cl-map-intervals - (list 'function (list 'lambda (list var1 var2) - '(progn . --cl-map))) - buf prop from to)))) - - ((memq word key-types) - (or (memq (car args) '(in of)) (error "Expected `of'")) - (let ((map (cl-pop2 args)) - (other (if (eq (car args) 'using) - (if (and (= (length (cadr args)) 2) - (memq (caadr args) key-types) - (not (eq (caadr args) word))) - (cadr (cl-pop2 args)) - (error "Bad `using' clause")) - (gensym)))) - (if (memq word '(key-binding key-bindings)) - (setq var (prog1 other (setq other var)))) - (setq loop-map-form - (list (if (memq word '(key-seq key-seqs)) - 'cl-map-keymap-recursively 'cl-map-keymap) - (list 'function (list* 'lambda (list var other) - '--cl-map)) map)))) - - ((memq word '(frame frames screen screens)) - (let ((temp (gensym))) - (cl-push (list var (if (eq cl-emacs-type 'lucid) - '(selected-screen) '(selected-frame))) - loop-for-bindings) - (cl-push (list temp nil) loop-for-bindings) - (cl-push (list 'prog1 (list 'not (list 'eq var temp)) - (list 'or temp (list 'setq temp var))) - loop-body) - (cl-push (list var (list (if (eq cl-emacs-type 'lucid) - 'next-screen 'next-frame) var)) - loop-for-steps))) - - ((memq word '(window windows)) - (let ((scr (and (memq (car args) '(in of)) (cl-pop2 args))) - (temp (gensym))) - (cl-push (list var (if scr - (list (if (eq cl-emacs-type 'lucid) - 'screen-selected-window - 'frame-selected-window) scr) - '(selected-window))) - loop-for-bindings) - (cl-push (list temp nil) loop-for-bindings) - (cl-push (list 'prog1 (list 'not (list 'eq var temp)) - (list 'or temp (list 'setq temp var))) - loop-body) - (cl-push (list var (list 'next-window var)) loop-for-steps))) - - (t - (let ((handler (and (symbolp word) - (get word 'cl-loop-for-handler)))) - (if handler - (funcall handler var) - (error "Expected a `for' preposition, found %s" word))))) - (eq (car args) 'and)) - (setq ands t) - (cl-pop args)) - (if (and ands loop-for-bindings) - (cl-push (nreverse loop-for-bindings) loop-bindings) - (setq loop-bindings (nconc (mapcar 'list loop-for-bindings) - loop-bindings))) - (if loop-for-sets - (cl-push (list 'progn - (cl-loop-let (nreverse loop-for-sets) 'setq ands) - t) loop-body)) - (if loop-for-steps - (cl-push (cons (if ands 'psetq 'setq) - (apply 'append (nreverse loop-for-steps))) - loop-steps)))) - - ((eq word 'repeat) - (let ((temp (gensym))) - (cl-push (list (list temp (cl-pop args))) loop-bindings) - (cl-push (list '>= (list 'setq temp (list '1- temp)) 0) loop-body))) - - ((eq word 'collect) - (let ((what (cl-pop args)) - (var (cl-loop-handle-accum nil 'nreverse))) - (if (eq var loop-accum-var) - (cl-push (list 'progn (list 'push what var) t) loop-body) - (cl-push (list 'progn - (list 'setq var (list 'nconc var (list 'list what))) - t) loop-body)))) - - ((memq word '(nconc nconcing append appending)) - (let ((what (cl-pop args)) - (var (cl-loop-handle-accum nil 'nreverse))) - (cl-push (list 'progn - (list 'setq var - (if (eq var loop-accum-var) - (list 'nconc - (list (if (memq word '(nconc nconcing)) - 'nreverse 'reverse) - what) - var) - (list (if (memq word '(nconc nconcing)) - 'nconc 'append) - var what))) t) loop-body))) - - ((memq word '(concat concating)) - (let ((what (cl-pop args)) - (var (cl-loop-handle-accum ""))) - (cl-push (list 'progn (list 'callf 'concat var what) t) loop-body))) - - ((memq word '(vconcat vconcating)) - (let ((what (cl-pop args)) - (var (cl-loop-handle-accum []))) - (cl-push (list 'progn (list 'callf 'vconcat var what) t) loop-body))) - - ((memq word '(sum summing)) - (let ((what (cl-pop args)) - (var (cl-loop-handle-accum 0))) - (cl-push (list 'progn (list 'incf var what) t) loop-body))) - - ((memq word '(count counting)) - (let ((what (cl-pop args)) - (var (cl-loop-handle-accum 0))) - (cl-push (list 'progn (list 'if what (list 'incf var)) t) loop-body))) - - ((memq word '(minimize minimizing maximize maximizing)) - (let* ((what (cl-pop args)) - (temp (if (cl-simple-expr-p what) what (gensym))) - (var (cl-loop-handle-accum nil)) - (func (intern (substring (symbol-name word) 0 3))) - (set (list 'setq var (list 'if var (list func var temp) temp)))) - (cl-push (list 'progn (if (eq temp what) set - (list 'let (list (list temp what)) set)) - t) loop-body))) - - ((eq word 'with) - (let ((bindings nil)) - (while (progn (cl-push (list (cl-pop args) - (and (eq (car args) '=) (cl-pop2 args))) - bindings) - (eq (car args) 'and)) - (cl-pop args)) - (cl-push (nreverse bindings) loop-bindings))) - - ((eq word 'while) - (cl-push (cl-pop args) loop-body)) - - ((eq word 'until) - (cl-push (list 'not (cl-pop args)) loop-body)) - - ((eq word 'always) - (or loop-finish-flag (setq loop-finish-flag (gensym))) - (cl-push (list 'setq loop-finish-flag (cl-pop args)) loop-body) - (setq loop-result t)) - - ((eq word 'never) - (or loop-finish-flag (setq loop-finish-flag (gensym))) - (cl-push (list 'setq loop-finish-flag (list 'not (cl-pop args))) - loop-body) - (setq loop-result t)) - - ((eq word 'thereis) - (or loop-finish-flag (setq loop-finish-flag (gensym))) - (or loop-result-var (setq loop-result-var (gensym))) - (cl-push (list 'setq loop-finish-flag - (list 'not (list 'setq loop-result-var (cl-pop args)))) - loop-body)) - - ((memq word '(if when unless)) - (let* ((cond (cl-pop args)) - (then (let ((loop-body nil)) - (cl-parse-loop-clause) - (cl-loop-build-ands (nreverse loop-body)))) - (else (let ((loop-body nil)) - (if (eq (car args) 'else) - (progn (cl-pop args) (cl-parse-loop-clause))) - (cl-loop-build-ands (nreverse loop-body)))) - (simple (and (eq (car then) t) (eq (car else) t)))) - (if (eq (car args) 'end) (cl-pop args)) - (if (eq word 'unless) (setq then (prog1 else (setq else then)))) - (let ((form (cons (if simple (cons 'progn (nth 1 then)) (nth 2 then)) - (if simple (nth 1 else) (list (nth 2 else)))))) - (if (cl-expr-contains form 'it) - (let ((temp (gensym))) - (cl-push (list temp) loop-bindings) - (setq form (list* 'if (list 'setq temp cond) - (subst temp 'it form)))) - (setq form (list* 'if cond form))) - (cl-push (if simple (list 'progn form t) form) loop-body)))) - - ((memq word '(do doing)) - (let ((body nil)) - (or (consp (car args)) (error "Syntax error on `do' clause")) - (while (consp (car args)) (cl-push (cl-pop args) body)) - (cl-push (cons 'progn (nreverse (cons t body))) loop-body))) - - ((eq word 'return) - (or loop-finish-flag (setq loop-finish-flag (gensym))) - (or loop-result-var (setq loop-result-var (gensym))) - (cl-push (list 'setq loop-result-var (cl-pop args) - loop-finish-flag nil) loop-body)) - - (t - (let ((handler (and (symbolp word) (get word 'cl-loop-handler)))) - (or handler (error "Expected a loop keyword, found %s" word)) - (funcall handler)))) - (if (eq (car args) 'and) - (progn (cl-pop args) (cl-parse-loop-clause))))) - -(defun cl-loop-let (specs body par) ; uses loop-* - (let ((p specs) (temps nil) (new nil)) - (while (and p (or (symbolp (car-safe (car p))) (null (cadar p)))) - (setq p (cdr p))) - (and par p - (progn - (setq par nil p specs) - (while p - (or (cl-const-expr-p (cadar p)) - (let ((temp (gensym))) - (cl-push (list temp (cadar p)) temps) - (setcar (cdar p) temp))) - (setq p (cdr p))))) - (while specs - (if (and (consp (car specs)) (listp (caar specs))) - (let* ((spec (caar specs)) (nspecs nil) - (expr (cadr (cl-pop specs))) - (temp (cdr (or (assq spec loop-destr-temps) - (car (cl-push (cons spec (or (last spec 0) - (gensym))) - loop-destr-temps)))))) - (cl-push (list temp expr) new) - (while (consp spec) - (cl-push (list (cl-pop spec) - (and expr (list (if spec 'pop 'car) temp))) - nspecs)) - (setq specs (nconc (nreverse nspecs) specs))) - (cl-push (cl-pop specs) new))) - (if (eq body 'setq) - (let ((set (cons (if par 'psetq 'setq) (apply 'nconc (nreverse new))))) - (if temps (list 'let* (nreverse temps) set) set)) - (list* (if par 'let 'let*) - (nconc (nreverse temps) (nreverse new)) body)))) - -(defun cl-loop-handle-accum (def &optional func) ; uses args, loop-* - (if (eq (car args) 'into) - (let ((var (cl-pop2 args))) - (or (memq var loop-accum-vars) - (progn (cl-push (list (list var def)) loop-bindings) - (cl-push var loop-accum-vars))) - var) - (or loop-accum-var - (progn - (cl-push (list (list (setq loop-accum-var (gensym)) def)) - loop-bindings) - (setq loop-result (if func (list func loop-accum-var) - loop-accum-var)) - loop-accum-var)))) - -(defun cl-loop-build-ands (clauses) - (let ((ands nil) - (body nil)) - (while clauses - (if (and (eq (car-safe (car clauses)) 'progn) - (eq (car (last (car clauses))) t)) - (if (cdr clauses) - (setq clauses (cons (nconc (butlast (car clauses)) - (if (eq (car-safe (cadr clauses)) - 'progn) - (cdadr clauses) - (list (cadr clauses)))) - (cddr clauses))) - (setq body (cdr (butlast (cl-pop clauses))))) - (cl-push (cl-pop clauses) ands))) - (setq ands (or (nreverse ands) (list t))) - (list (if (cdr ands) (cons 'and ands) (car ands)) - body - (let ((full (if body - (append ands (list (cons 'progn (append body '(t))))) - ands))) - (if (cdr full) (cons 'and full) (car full)))))) - - -;;; Other iteration control structures. - -;;;###autoload -(defmacro do (steps endtest &rest body) - "The Common Lisp `do' loop. -Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" - (cl-expand-do-loop steps endtest body nil)) - -;;;###autoload -(defmacro do* (steps endtest &rest body) - "The Common Lisp `do*' loop. -Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" - (cl-expand-do-loop steps endtest body t)) - -(defun cl-expand-do-loop (steps endtest body star) - (list 'block nil - (list* (if star 'let* 'let) - (mapcar (function (lambda (c) - (if (consp c) (list (car c) (nth 1 c)) c))) - steps) - (list* 'while (list 'not (car endtest)) - (append body - (let ((sets (mapcar - (function - (lambda (c) - (and (consp c) (cdr (cdr c)) - (list (car c) (nth 2 c))))) - steps))) - (setq sets (delq nil sets)) - (and sets - (list (cons (if (or star (not (cdr sets))) - 'setq 'psetq) - (apply 'append sets))))))) - (or (cdr endtest) '(nil))))) - -;;;###autoload -(defmacro dolist (spec &rest body) - "(dolist (VAR LIST [RESULT]) BODY...): loop over a list. -Evaluate BODY with VAR bound to each `car' from LIST, in turn. -Then evaluate RESULT to get return value, default nil." - (let ((temp (gensym "--dolist-temp--"))) - (list 'block nil - (list* 'let (list (list temp (nth 1 spec)) (car spec)) - (list* 'while temp (list 'setq (car spec) (list 'car temp)) - (append body (list (list 'setq temp - (list 'cdr temp))))) - (if (cdr (cdr spec)) - (cons (list 'setq (car spec) nil) (cdr (cdr spec))) - '(nil)))))) - -;;;###autoload -(defmacro dotimes (spec &rest body) - "(dotimes (VAR COUNT [RESULT]) BODY...): loop a certain number of times. -Evaluate BODY with VAR bound to successive integers from 0, inclusive, -to COUNT, exclusive. Then evaluate RESULT to get return value, default -nil." - (let ((temp (gensym "--dotimes-temp--"))) - (list 'block nil - (list* 'let (list (list temp (nth 1 spec)) (list (car spec) 0)) - (list* 'while (list '< (car spec) temp) - (append body (list (list 'incf (car spec))))) - (or (cdr (cdr spec)) '(nil)))))) - -;;;###autoload -(defmacro do-symbols (spec &rest body) - "(dosymbols (VAR [OBARRAY [RESULT]]) BODY...): loop over all symbols. -Evaluate BODY with VAR bound to each interned symbol, or to each symbol -from OBARRAY." - ;; Apparently this doesn't have an implicit block. - (list 'block nil - (list 'let (list (car spec)) - (list* 'mapatoms - (list 'function (list* 'lambda (list (car spec)) body)) - (and (cadr spec) (list (cadr spec)))) - (caddr spec)))) - -;;;###autoload -(defmacro do-all-symbols (spec &rest body) - (list* 'do-symbols (list (car spec) nil (cadr spec)) body)) - - -;;; Assignments. - -;;;###autoload -(defmacro psetq (&rest args) - "(psetq SYM VAL SYM VAL ...): set SYMs to the values VALs in parallel. -This is like `setq', except that all VAL forms are evaluated (in order) -before assigning any symbols SYM to the corresponding values." - (cons 'psetf args)) - - -;;; Binding control structures. - -;;;###autoload -(defmacro progv (symbols values &rest body) - "(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY. -The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. -Each SYMBOL in the first list is bound to the corresponding VALUE in the -second list (or made unbound if VALUES is shorter than SYMBOLS); then the -BODY forms are executed and their result is returned. This is much like -a `let' form, except that the list of symbols can be computed at run-time." - (list 'let '((cl-progv-save nil)) - (list 'unwind-protect - (list* 'progn (list 'cl-progv-before symbols values) body) - '(cl-progv-after)))) - -;;; This should really have some way to shadow 'byte-compile properties, etc. -;;;###autoload -(defmacro flet (bindings &rest body) - "(flet ((FUNC ARGLIST BODY...) ...) FORM...): make temporary function defns. -This is an analogue of `let' that operates on the function cell of FUNC -rather than its value cell. The FORMs are evaluated with the specified -function definitions in place, then the definitions are undone (the FUNCs -go back to their previous definitions, or lack thereof)." - (list* 'letf* - (mapcar - (function - (lambda (x) - (if (or (and (fboundp (car x)) - (eq (car-safe (symbol-function (car x))) 'macro)) - (cdr (assq (car x) cl-macro-environment))) - (error "Use `labels', not `flet', to rebind macro names")) - (let ((func (list 'function* - (list 'lambda (cadr x) - (list* 'block (car x) (cddr x)))))) - (if (and (cl-compiling-file) - (boundp 'byte-compile-function-environment)) - (cl-push (cons (car x) (eval func)) - byte-compile-function-environment)) - (list (list 'symbol-function (list 'quote (car x))) func)))) - bindings) - body)) - -;;;###autoload -(defmacro labels (bindings &rest body) - "(labels ((FUNC ARGLIST BODY...) ...) FORM...): make temporary func bindings. -This is like `flet', except the bindings are lexical instead of dynamic. -Unlike `flet', this macro is fully complaint with the Common Lisp standard." - (let ((vars nil) (sets nil) (cl-macro-environment cl-macro-environment)) - (while bindings - (let ((var (gensym))) - (cl-push var vars) - (cl-push (list 'function* (cons 'lambda (cdar bindings))) sets) - (cl-push var sets) - (cl-push (list (car (cl-pop bindings)) 'lambda '(&rest cl-labels-args) - (list 'list* '(quote funcall) (list 'quote var) - 'cl-labels-args)) - cl-macro-environment))) - (cl-macroexpand-all (list* 'lexical-let vars (cons (cons 'setq sets) body)) - cl-macro-environment))) - -;; The following ought to have a better definition for use with newer -;; byte compilers. -;;;###autoload -(defmacro macrolet (bindings &rest body) - "(macrolet ((NAME ARGLIST BODY...) ...) FORM...): make temporary macro defns. -This is like `flet', but for macros instead of functions." - (if (cdr bindings) - (list 'macrolet - (list (car bindings)) (list* 'macrolet (cdr bindings) body)) - (if (null bindings) (cons 'progn body) - (let* ((name (caar bindings)) - (res (cl-transform-lambda (cdar bindings) name))) - (eval (car res)) - (cl-macroexpand-all (cons 'progn body) - (cons (list* name 'lambda (cdr res)) - cl-macro-environment)))))) - -;;;###autoload -(defmacro symbol-macrolet (bindings &rest body) - "(symbol-macrolet ((NAME EXPANSION) ...) FORM...): make symbol macro defns. -Within the body FORMs, references to the variable NAME will be replaced -by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)." - (if (cdr bindings) - (list 'symbol-macrolet - (list (car bindings)) (list* 'symbol-macrolet (cdr bindings) body)) - (if (null bindings) (cons 'progn body) - (cl-macroexpand-all (cons 'progn body) - (cons (list (symbol-name (caar bindings)) - (cadar bindings)) - cl-macro-environment))))) - -(defvar cl-closure-vars nil) -;;;###autoload -(defmacro lexical-let (bindings &rest body) - "(lexical-let BINDINGS BODY...): like `let', but lexically scoped. -The main visible difference is that lambdas inside BODY will create -lexical closures as in Common Lisp." - (let* ((cl-closure-vars cl-closure-vars) - (vars (mapcar (function - (lambda (x) - (or (consp x) (setq x (list x))) - (cl-push (gensym (format "--%s--" (car x))) - cl-closure-vars) - (list (car x) (cadr x) (car cl-closure-vars)))) - bindings)) - (ebody - (cl-macroexpand-all - (cons 'progn body) - (nconc (mapcar (function (lambda (x) - (list (symbol-name (car x)) - (list 'symbol-value (caddr x)) - t))) vars) - (list '(defun . cl-defun-expander)) - cl-macro-environment)))) - (if (not (get (car (last cl-closure-vars)) 'used)) - (list 'let (mapcar (function (lambda (x) - (list (caddr x) (cadr x)))) vars) - (sublis (mapcar (function (lambda (x) - (cons (caddr x) - (list 'quote (caddr x))))) - vars) - ebody)) - (list 'let (mapcar (function (lambda (x) - (list (caddr x) - (list 'make-symbol - (format "--%s--" (car x)))))) - vars) - (apply 'append '(setf) - (mapcar (function - (lambda (x) - (list (list 'symbol-value (caddr x)) (cadr x)))) - vars)) - ebody)))) - -;;;###autoload -(defmacro lexical-let* (bindings &rest body) - "(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped. -The main visible difference is that lambdas inside BODY will create -lexical closures as in Common Lisp." - (if (null bindings) (cons 'progn body) - (setq bindings (reverse bindings)) - (while bindings - (setq body (list (list* 'lexical-let (list (cl-pop bindings)) body)))) - (car body))) - -(defun cl-defun-expander (func &rest rest) - (list 'progn - (list 'defalias (list 'quote func) - (list 'function (cons 'lambda rest))) - (list 'quote func))) - - -;;; Multiple values. - -;;;###autoload -(defmacro multiple-value-bind (vars form &rest body) - "(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values. -FORM must return a list; the BODY is then executed with the first N elements -of this list bound (`let'-style) to each of the symbols SYM in turn. This -is analogous to the Common Lisp `multiple-value-bind' macro, using lists to -simulate true multiple return values. For compatibility, (values A B C) is -a synonym for (list A B C)." - (let ((temp (gensym)) (n -1)) - (list* 'let* (cons (list temp form) - (mapcar (function - (lambda (v) - (list v (list 'nth (setq n (1+ n)) temp)))) - vars)) - body))) - -;;;###autoload -(defmacro multiple-value-setq (vars form) - "(multiple-value-setq (SYM SYM...) FORM): collect multiple return values. -FORM must return a list; the first N elements of this list are stored in -each of the symbols SYM in turn. This is analogous to the Common Lisp -`multiple-value-setq' macro, using lists to simulate true multiple return -values. For compatibility, (values A B C) is a synonym for (list A B C)." - (cond ((null vars) (list 'progn form nil)) - ((null (cdr vars)) (list 'setq (car vars) (list 'car form))) - (t - (let* ((temp (gensym)) (n 0)) - (list 'let (list (list temp form)) - (list 'prog1 (list 'setq (cl-pop vars) (list 'car temp)) - (cons 'setq (apply 'nconc - (mapcar (function - (lambda (v) - (list v (list - 'nth - (setq n (1+ n)) - temp)))) - vars))))))))) - - -;;; Declarations. - -;;;###autoload -(defmacro locally (&rest body) (cons 'progn body)) -;;;###autoload -(defmacro the (type form) form) - -(defvar cl-proclaim-history t) ; for future compilers -(defvar cl-declare-stack t) ; for future compilers - -(defun cl-do-proclaim (spec hist) - (and hist (listp cl-proclaim-history) (cl-push spec cl-proclaim-history)) - (cond ((eq (car-safe spec) 'special) - (if (boundp 'byte-compile-bound-variables) - (setq byte-compile-bound-variables - ;; todo: this should compute correct binding bits vs. 0 - (append (mapcar #'(lambda (v) (cons v 0)) - (cdr spec)) - byte-compile-bound-variables)))) - - ((eq (car-safe spec) 'inline) - (while (setq spec (cdr spec)) - (or (memq (get (car spec) 'byte-optimizer) - '(nil byte-compile-inline-expand)) - (error "%s already has a byte-optimizer, can't make it inline" - (car spec))) - (put (car spec) 'byte-optimizer 'byte-compile-inline-expand))) - - ((eq (car-safe spec) 'notinline) - (while (setq spec (cdr spec)) - (if (eq (get (car spec) 'byte-optimizer) - 'byte-compile-inline-expand) - (put (car spec) 'byte-optimizer nil)))) - - ((eq (car-safe spec) 'optimize) - (let ((speed (assq (nth 1 (assq 'speed (cdr spec))) - '((0 nil) (1 t) (2 t) (3 t)))) - (safety (assq (nth 1 (assq 'safety (cdr spec))) - '((0 t) (1 t) (2 t) (3 nil))))) - (if speed (setq cl-optimize-speed (car speed) - byte-optimize (nth 1 speed))) - (if safety (setq cl-optimize-safety (car safety) - byte-compile-delete-errors (nth 1 safety))))) - - ((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings)) - (if (eq byte-compile-warnings t) - ;; XEmacs change - (setq byte-compile-warnings byte-compile-default-warnings)) - (while (setq spec (cdr spec)) - (if (consp (car spec)) - (if (eq (cadar spec) 0) - (setq byte-compile-warnings - (delq (caar spec) byte-compile-warnings)) - (setq byte-compile-warnings - (adjoin (caar spec) byte-compile-warnings))))))) - nil) - -;;; Process any proclamations made before cl-macs was loaded. -(defvar cl-proclaims-deferred) -(let ((p (reverse cl-proclaims-deferred))) - (while p (cl-do-proclaim (cl-pop p) t)) - (setq cl-proclaims-deferred nil)) - -;;;###autoload -(defmacro declare (&rest specs) - (if (cl-compiling-file) - (while specs - (if (listp cl-declare-stack) (cl-push (car specs) cl-declare-stack)) - (cl-do-proclaim (cl-pop specs) nil))) - nil) - - - -;;; Generalized variables. - -;;;###autoload -(defmacro define-setf-method (func args &rest body) - "(define-setf-method NAME ARGLIST BODY...): define a `setf' method. -This method shows how to handle `setf's to places of the form (NAME ARGS...). -The argument forms ARGS are bound according to ARGLIST, as if NAME were -going to be expanded as a macro, then the BODY forms are executed and must -return a list of five elements: a temporary-variables list, a value-forms -list, a store-variables list (of length one), a store-form, and an access- -form. See `defsetf' for a simpler way to define most setf-methods." - (append '(eval-when (compile load eval)) - (if (stringp (car body)) - (list (list 'put (list 'quote func) '(quote setf-documentation) - (cl-pop body)))) - (list (cl-transform-function-property - func 'setf-method (cons args body))))) - -;;;###autoload -(defmacro defsetf (func arg1 &rest args) - "(defsetf NAME FUNC): define a `setf' method. -This macro is an easy-to-use substitute for `define-setf-method' that works -well for simple place forms. In the simple `defsetf' form, `setf's of -the form (setf (NAME ARGS...) VAL) are transformed to function or macro -calls of the form (FUNC ARGS... VAL). Example: (defsetf aref aset). -Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). -Here, the above `setf' call is expanded by binding the argument forms ARGS -according to ARGLIST, binding the value form VAL to STORE, then executing -BODY, which must return a Lisp form that does the necessary `setf' operation. -Actually, ARGLIST and STORE may be bound to temporary variables which are -introduced automatically to preserve proper execution order of the arguments. -Example: (defsetf nth (n x) (v) (list 'setcar (list 'nthcdr n x) v))." - (if (listp arg1) - (let* ((largs nil) (largsr nil) - (temps nil) (tempsr nil) - (restarg nil) (rest-temps nil) - (store-var (car (prog1 (car args) (setq args (cdr args))))) - (store-temp (intern (format "--%s--temp--" store-var))) - (lets1 nil) (lets2 nil) - (docstr nil) (p arg1)) - (if (stringp (car args)) - (setq docstr (prog1 (car args) (setq args (cdr args))))) - (while (and p (not (eq (car p) '&aux))) - (if (eq (car p) '&rest) - (setq p (cdr p) restarg (car p)) - (or (memq (car p) '(&optional &key &allow-other-keys)) - (setq largs (cons (if (consp (car p)) (car (car p)) (car p)) - largs) - temps (cons (intern (format "--%s--temp--" (car largs))) - temps)))) - (setq p (cdr p))) - (setq largs (nreverse largs) temps (nreverse temps)) - (if restarg - (setq largsr (append largs (list restarg)) - rest-temps (intern (format "--%s--temp--" restarg)) - tempsr (append temps (list rest-temps))) - (setq largsr largs tempsr temps)) - (let ((p1 largs) (p2 temps)) - (while p1 - (setq lets1 (cons (list (car p2) - (list 'gensym (format "--%s--" (car p1)))) - lets1) - lets2 (cons (list (car p1) (car p2)) lets2) - p1 (cdr p1) p2 (cdr p2)))) - (if restarg (setq lets2 (cons (list restarg rest-temps) lets2))) - (append (list 'define-setf-method func arg1) - (and docstr (list docstr)) - (list - (list 'let* - (nreverse - (cons (list store-temp - (list 'gensym (format "--%s--" store-var))) - (if restarg - (append - (list - (list rest-temps - (list 'mapcar '(quote gensym) - restarg))) - lets1) - lets1))) - (list 'list ; 'values - (cons (if restarg 'list* 'list) tempsr) - (cons (if restarg 'list* 'list) largsr) - (list 'list store-temp) - (cons 'let* - (cons (nreverse - (cons (list store-var store-temp) - lets2)) - args)) - (cons (if restarg 'list* 'list) - (cons (list 'quote func) tempsr))))))) - (list 'defsetf func '(&rest args) '(store) - (let ((call (list 'cons (list 'quote arg1) - '(append args (list store))))) - (if (car args) - (list 'list '(quote progn) call 'store) - call))))) - -;;; Some standard place types from Common Lisp. -(defsetf aref aset) -(defsetf car setcar) -(defsetf cdr setcdr) -(defsetf elt (seq n) (store) - (list 'if (list 'listp seq) (list 'setcar (list 'nthcdr n seq) store) - (list 'aset seq n store))) -(defsetf get (x y &optional d) (store) (list 'put x y store)) -(defsetf get* (x y &optional d) (store) (list 'put x y store)) -(defsetf gethash (x h &optional d) (store) (list 'cl-puthash x store h)) -(defsetf nth (n x) (store) (list 'setcar (list 'nthcdr n x) store)) -(defsetf subseq (seq start &optional end) (new) - (list 'progn (list 'replace seq new ':start1 start ':end1 end) new)) -(defsetf symbol-function fset) -(defsetf symbol-plist setplist) -(defsetf symbol-value set) - -;;; Various car/cdr aliases. Note that `cadr' is handled specially. -(defsetf first setcar) -(defsetf second (x) (store) (list 'setcar (list 'cdr x) store)) -(defsetf third (x) (store) (list 'setcar (list 'cddr x) store)) -(defsetf fourth (x) (store) (list 'setcar (list 'cdddr x) store)) -(defsetf fifth (x) (store) (list 'setcar (list 'nthcdr 4 x) store)) -(defsetf sixth (x) (store) (list 'setcar (list 'nthcdr 5 x) store)) -(defsetf seventh (x) (store) (list 'setcar (list 'nthcdr 6 x) store)) -(defsetf eighth (x) (store) (list 'setcar (list 'nthcdr 7 x) store)) -(defsetf ninth (x) (store) (list 'setcar (list 'nthcdr 8 x) store)) -(defsetf tenth (x) (store) (list 'setcar (list 'nthcdr 9 x) store)) -(defsetf rest setcdr) - -;;; Some more Emacs-related place types. -(defsetf buffer-file-name set-visited-file-name t) -(defsetf buffer-modified-p set-buffer-modified-p t) -(defsetf buffer-name rename-buffer t) -(defsetf buffer-string () (store) - (list 'progn '(erase-buffer) (list 'insert store))) -(defsetf buffer-substring cl-set-buffer-substring) -(defsetf current-buffer set-buffer) -(defsetf current-case-table set-case-table) -(defsetf current-column move-to-column t) -(defsetf current-global-map use-global-map t) -(defsetf current-input-mode () (store) - (list 'progn (list 'apply 'set-input-mode store) store)) -(defsetf current-local-map use-local-map t) -(defsetf current-window-configuration set-window-configuration t) -(defsetf default-file-modes set-default-file-modes t) -(defsetf default-value set-default) -(defsetf documentation-property put) -(defsetf extent-data set-extent-data) ; obsolete -(defsetf extent-face set-extent-face) -(defsetf extent-priority set-extent-priority) -(defsetf extent-property (x y &optional d) (arg) - (list 'set-extent-property x y arg)) -(defsetf extent-end-position (ext) (store) - (list 'progn (list 'set-extent-endpoints (list 'extent-start-position ext) - store) store)) -(defsetf extent-start-position (ext) (store) - (list 'progn (list 'set-extent-endpoints store - (list 'extent-end-position ext)) store)) -(defsetf face-background (f &optional s) (x) (list 'set-face-background f x s)) -(defsetf face-background-pixmap (f &optional s) (x) - (list 'set-face-background-pixmap f x s)) -(defsetf face-font (f &optional s) (x) (list 'set-face-font f x s)) -(defsetf face-foreground (f &optional s) (x) (list 'set-face-foreground f x s)) -(defsetf face-underline-p (f &optional s) (x) - (list 'set-face-underline-p f x s)) -(defsetf file-modes set-file-modes t) -(defsetf frame-parameters modify-frame-parameters t) -(defsetf frame-visible-p cl-set-frame-visible-p) -(defsetf frame-properties (&optional f) (p) - `(progn (set-frame-properties ,f ,p) ,p)) -(defsetf frame-property (f p &optional d) (v) - `(progn (set-frame-property ,f ,v) ,p)) -(defsetf frame-width (&optional f) (v) - `(progn (set-frame-width ,f ,v) ,v)) -(defsetf frame-height (&optional f) (v) - `(progn (set-frame-height ,f ,v) ,v)) -(defsetf current-frame-configuration set-frame-configuration) - -;; XEmacs: new stuff -;; Consoles -(defsetf selected-console select-console t) -(defsetf selected-device select-device t) -(defsetf device-baud-rate (&optional d) (v) - `(set-device-baud-rate ,d ,v)) -(defsetf specifier-instance (spec &optional dom def nof) (val) - `(set-specifier ,spec ,val ,dom)) - -;; Annotations -(defsetf annotation-glyph set-annotation-glyph) -(defsetf annotation-down-glyph set-annotation-down-glyph) -(defsetf annotation-face set-annotation-face) -(defsetf annotation-layout set-annotation-layout) -(defsetf annotation-data set-annotation-data) -(defsetf annotation-action set-annotation-action) -(defsetf annotation-menu set-annotation-menu) -;; Widget -(defsetf widget-get widget-put t) -(defsetf widget-value widget-value-set t) - -;; Misc -(defsetf recent-keys-ring-size set-recent-keys-ring-size) - -(defsetf getenv setenv t) -(defsetf get-register set-register) -(defsetf global-key-binding global-set-key) -(defsetf keymap-parent set-keymap-parent) -(defsetf keymap-name set-keymap-name) -(defsetf keymap-prompt set-keymap-prompt) -(defsetf keymap-default-binding set-keymap-default-binding) -(defsetf local-key-binding local-set-key) -(defsetf mark set-mark t) -(defsetf mark-marker set-mark t) -(defsetf marker-position set-marker t) -(defsetf match-data store-match-data t) -(defsetf mouse-position (scr) (store) - (list 'set-mouse-position scr (list 'car store) (list 'cadr store) - (list 'cddr store))) -(defsetf overlay-get overlay-put) -(defsetf overlay-start (ov) (store) - (list 'progn (list 'move-overlay ov store (list 'overlay-end ov)) store)) -(defsetf overlay-end (ov) (store) - (list 'progn (list 'move-overlay ov (list 'overlay-start ov) store) store)) -(defsetf point goto-char) -(defsetf point-marker goto-char t) -(defsetf point-max () (store) - (list 'progn (list 'narrow-to-region '(point-min) store) store)) -(defsetf point-min () (store) - (list 'progn (list 'narrow-to-region store '(point-max)) store)) -(defsetf process-buffer set-process-buffer) -(defsetf process-filter set-process-filter) -(defsetf process-sentinel set-process-sentinel) -(defsetf read-mouse-position (scr) (store) - (list 'set-mouse-position scr (list 'car store) (list 'cdr store))) -(defsetf screen-height set-screen-height t) -(defsetf screen-width set-screen-width t) -(defsetf selected-window select-window) -(defsetf selected-screen select-screen) -(defsetf selected-frame select-frame) -(defsetf standard-case-table set-standard-case-table) -(defsetf syntax-table set-syntax-table) -(defsetf visited-file-modtime set-visited-file-modtime t) -(defsetf window-buffer set-window-buffer t) -(defsetf window-display-table set-window-display-table t) -(defsetf window-dedicated-p set-window-dedicated-p t) -(defsetf window-height () (store) - (list 'progn (list 'enlarge-window (list '- store '(window-height))) store)) -(defsetf window-hscroll set-window-hscroll) -(defsetf window-point set-window-point) -(defsetf window-start set-window-start) -(defsetf window-width () (store) - (list 'progn (list 'enlarge-window (list '- store '(window-width)) t) store)) -(defsetf x-get-cutbuffer x-store-cutbuffer t) -(defsetf x-get-cut-buffer x-store-cut-buffer t) ; groan. -(defsetf x-get-secondary-selection x-own-secondary-selection t) -(defsetf x-get-selection x-own-selection t) - -;;; More complex setf-methods. -;;; These should take &environment arguments, but since full arglists aren't -;;; available while compiling cl-macs, we fake it by referring to the global -;;; variable cl-macro-environment directly. - -(define-setf-method apply (func arg1 &rest rest) - (or (and (memq (car-safe func) '(quote function function*)) - (symbolp (car-safe (cdr-safe func)))) - (error "First arg to apply in setf is not (function SYM): %s" func)) - (let* ((form (cons (nth 1 func) (cons arg1 rest))) - (method (get-setf-method form cl-macro-environment))) - (list (car method) (nth 1 method) (nth 2 method) - (cl-setf-make-apply (nth 3 method) (cadr func) (car method)) - (cl-setf-make-apply (nth 4 method) (cadr func) (car method))))) - -(defun cl-setf-make-apply (form func temps) - (if (eq (car form) 'progn) - (list* 'progn (cl-setf-make-apply (cadr form) func temps) (cddr form)) - (or (equal (last form) (last temps)) - (error "%s is not suitable for use with setf-of-apply" func)) - (list* 'apply (list 'quote (car form)) (cdr form)))) - -(define-setf-method nthcdr (n place) - (let ((method (get-setf-method place cl-macro-environment)) - (n-temp (gensym "--nthcdr-n--")) - (store-temp (gensym "--nthcdr-store--"))) - (list (cons n-temp (car method)) - (cons n (nth 1 method)) - (list store-temp) - (list 'let (list (list (car (nth 2 method)) - (list 'cl-set-nthcdr n-temp (nth 4 method) - store-temp))) - (nth 3 method) store-temp) - (list 'nthcdr n-temp (nth 4 method))))) - -(define-setf-method getf (place tag &optional def) - (let ((method (get-setf-method place cl-macro-environment)) - (tag-temp (gensym "--getf-tag--")) - (def-temp (gensym "--getf-def--")) - (store-temp (gensym "--getf-store--"))) - (list (append (car method) (list tag-temp def-temp)) - (append (nth 1 method) (list tag def)) - (list store-temp) - (list 'let (list (list (car (nth 2 method)) - (list 'cl-set-getf (nth 4 method) - tag-temp store-temp))) - (nth 3 method) store-temp) - (list 'getf (nth 4 method) tag-temp def-temp)))) - -(define-setf-method substring (place from &optional to) - (let ((method (get-setf-method place cl-macro-environment)) - (from-temp (gensym "--substring-from--")) - (to-temp (gensym "--substring-to--")) - (store-temp (gensym "--substring-store--"))) - (list (append (car method) (list from-temp to-temp)) - (append (nth 1 method) (list from to)) - (list store-temp) - (list 'let (list (list (car (nth 2 method)) - (list 'cl-set-substring (nth 4 method) - from-temp to-temp store-temp))) - (nth 3 method) store-temp) - (list 'substring (nth 4 method) from-temp to-temp)))) - -(define-setf-method values (&rest args) - (let ((methods (mapcar #'(lambda (x) - (get-setf-method x cl-macro-environment)) - args)) - (store-temp (gensym "--values-store--"))) - (list (apply 'append (mapcar 'first methods)) - (apply 'append (mapcar 'second methods)) - (list store-temp) - (cons 'list - (mapcar #'(lambda (m) - (cl-setf-do-store (cons (car (third m)) (fourth m)) - (list 'pop store-temp))) - methods)) - (cons 'list (mapcar 'fifth methods))))) - -;;; Getting and optimizing setf-methods. -;;;###autoload -(defun get-setf-method (place &optional env) - "Return a list of five values describing the setf-method for PLACE. -PLACE may be any Lisp form which can appear as the PLACE argument to -a macro like `setf' or `incf'." - (if (symbolp place) - (let ((temp (gensym "--setf--"))) - (list nil nil (list temp) (list 'setq place temp) place)) - (or (and (symbolp (car place)) - (let* ((func (car place)) - (name (symbol-name func)) - (method (get func 'setf-method)) - (case-fold-search nil)) - (or (and method - (let ((cl-macro-environment env)) - (setq method (apply method (cdr place)))) - (if (and (consp method) (= (length method) 5)) - method - (error "Setf-method for %s returns malformed method" - func))) - (and (save-match-data - (string-match "\\`c[ad][ad][ad]?[ad]?r\\'" name)) - (get-setf-method (compiler-macroexpand place))) - (and (eq func 'edebug-after) - (get-setf-method (nth (1- (length place)) place) - env))))) - (if (eq place (setq place (macroexpand place env))) - (if (and (symbolp (car place)) (fboundp (car place)) - (symbolp (symbol-function (car place)))) - (get-setf-method (cons (symbol-function (car place)) - (cdr place)) env) - (error "No setf-method known for %s" (car place))) - (get-setf-method place env))))) - -(defun cl-setf-do-modify (place opt-expr) - (let* ((method (get-setf-method place cl-macro-environment)) - (temps (car method)) (values (nth 1 method)) - (lets nil) (subs nil) - (optimize (and (not (eq opt-expr 'no-opt)) - (or (and (not (eq opt-expr 'unsafe)) - (cl-safe-expr-p opt-expr)) - (cl-setf-simple-store-p (car (nth 2 method)) - (nth 3 method))))) - (simple (and optimize (consp place) (cl-simple-exprs-p (cdr place))))) - (while values - (if (or simple (cl-const-expr-p (car values))) - (cl-push (cons (cl-pop temps) (cl-pop values)) subs) - (cl-push (list (cl-pop temps) (cl-pop values)) lets))) - (list (nreverse lets) - (cons (car (nth 2 method)) (sublis subs (nth 3 method))) - (sublis subs (nth 4 method))))) - -(defun cl-setf-do-store (spec val) - (let ((sym (car spec)) - (form (cdr spec))) - (if (or (cl-const-expr-p val) - (and (cl-simple-expr-p val) (eq (cl-expr-contains form sym) 1)) - (cl-setf-simple-store-p sym form)) - (subst val sym form) - (list 'let (list (list sym val)) form)))) - -(defun cl-setf-simple-store-p (sym form) - (and (consp form) (eq (cl-expr-contains form sym) 1) - (eq (nth (1- (length form)) form) sym) - (symbolp (car form)) (fboundp (car form)) - (not (eq (car-safe (symbol-function (car form))) 'macro)))) - -;;; The standard modify macros. -;;;###autoload -(defmacro setf (&rest args) - "(setf PLACE VAL PLACE VAL ...): set each PLACE to the value of its VAL. -This is a generalized version of `setq'; the PLACEs may be symbolic -references such as (car x) or (aref x i), as well as plain symbols. -For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y). -The return value is the last VAL in the list." - (if (cdr (cdr args)) - (let ((sets nil)) - (while args (cl-push (list 'setf (cl-pop args) (cl-pop args)) sets)) - (cons 'progn (nreverse sets))) - (if (symbolp (car args)) - (and args (cons 'setq args)) - (let* ((method (cl-setf-do-modify (car args) (nth 1 args))) - (store (cl-setf-do-store (nth 1 method) (nth 1 args)))) - (if (car method) (list 'let* (car method) store) store))))) - -;;;###autoload -(defmacro psetf (&rest args) - "(psetf PLACE VAL PLACE VAL ...): set PLACEs to the values VALs in parallel. -This is like `setf', except that all VAL forms are evaluated (in order) -before assigning any PLACEs to the corresponding values." - (let ((p args) (simple t) (vars nil)) - (while p - (if (or (not (symbolp (car p))) (cl-expr-depends-p (nth 1 p) vars)) - (setq simple nil)) - (if (memq (car p) vars) - (error "Destination duplicated in psetf: %s" (car p))) - (cl-push (cl-pop p) vars) - (or p (error "Odd number of arguments to psetf")) - (cl-pop p)) - (if simple - (list 'progn (cons 'setf args) nil) - (setq args (reverse args)) - (let ((expr (list 'setf (cadr args) (car args)))) - (while (setq args (cddr args)) - (setq expr (list 'setf (cadr args) (list 'prog1 (car args) expr)))) - (list 'progn expr nil))))) - -;;;###autoload -(defun cl-do-pop (place) - (if (cl-simple-expr-p place) - (list 'prog1 (list 'car place) (list 'setf place (list 'cdr place))) - (let* ((method (cl-setf-do-modify place t)) - (temp (gensym "--pop--"))) - (list 'let* - (append (car method) - (list (list temp (nth 2 method)))) - (list 'prog1 - (list 'car temp) - (cl-setf-do-store (nth 1 method) (list 'cdr temp))))))) - -;;;###autoload -(defmacro remf (place tag) - "(remf PLACE TAG): remove TAG from property list PLACE. -PLACE may be a symbol, or any generalized variable allowed by `setf'. -The form returns true if TAG was found and removed, nil otherwise." - (let* ((method (cl-setf-do-modify place t)) - (tag-temp (and (not (cl-const-expr-p tag)) (gensym "--remf-tag--"))) - (val-temp (and (not (cl-simple-expr-p place)) - (gensym "--remf-place--"))) - (ttag (or tag-temp tag)) - (tval (or val-temp (nth 2 method)))) - (list 'let* - (append (car method) - (and val-temp (list (list val-temp (nth 2 method)))) - (and tag-temp (list (list tag-temp tag)))) - (list 'if (list 'eq ttag (list 'car tval)) - (list 'progn - (cl-setf-do-store (nth 1 method) (list 'cddr tval)) - t) - (list 'cl-do-remf tval ttag))))) - -;;;###autoload -(defmacro shiftf (place &rest args) - "(shiftf PLACE PLACE... VAL): shift left among PLACEs. -Example: (shiftf A B C) sets A to B, B to C, and returns the old A. -Each PLACE may be a symbol, or any generalized variable allowed by `setf'." - (if (not (memq nil (mapcar 'symbolp (butlast (cons place args))))) - (list* 'prog1 place - (let ((sets nil)) - (while args - (cl-push (list 'setq place (car args)) sets) - (setq place (cl-pop args))) - (nreverse sets))) - (let* ((places (reverse (cons place args))) - (form (cl-pop places))) - (while places - (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe))) - (setq form (list 'let* (car method) - (list 'prog1 (nth 2 method) - (cl-setf-do-store (nth 1 method) form)))))) - form))) - -;;;###autoload -(defmacro rotatef (&rest args) - "(rotatef PLACE...): rotate left among PLACEs. -Example: (rotatef A B C) sets A to B, B to C, and C to A. It returns nil. -Each PLACE may be a symbol, or any generalized variable allowed by `setf'." - (if (not (memq nil (mapcar 'symbolp args))) - (and (cdr args) - (let ((sets nil) - (first (car args))) - (while (cdr args) - (setq sets (nconc sets (list (cl-pop args) (car args))))) - (nconc (list 'psetf) sets (list (car args) first)))) - (let* ((places (reverse args)) - (temp (gensym "--rotatef--")) - (form temp)) - (while (cdr places) - (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe))) - (setq form (list 'let* (car method) - (list 'prog1 (nth 2 method) - (cl-setf-do-store (nth 1 method) form)))))) - (let ((method (cl-setf-do-modify (car places) 'unsafe))) - (list 'let* (append (car method) (list (list temp (nth 2 method)))) - (cl-setf-do-store (nth 1 method) form) nil))))) - -;;;###autoload -(defmacro letf (bindings &rest body) - "(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. -This is the analogue of `let', but with generalized variables (in the -sense of `setf') for the PLACEs. Each PLACE is set to the corresponding -VALUE, then the BODY forms are executed. On exit, either normally or -because of a `throw' or error, the PLACEs are set back to their original -values. Note that this macro is *not* available in Common Lisp. -As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', -the PLACE is not modified before executing BODY." - (if (and (not (cdr bindings)) (cdar bindings) (symbolp (caar bindings))) - (list* 'let bindings body) - (let ((lets nil) (sets nil) - (unsets nil) (rev (reverse bindings))) - (while rev - (let* ((place (if (symbolp (caar rev)) - (list 'symbol-value (list 'quote (caar rev))) - (caar rev))) - (value (cadar rev)) - (method (cl-setf-do-modify place 'no-opt)) - (save (gensym "--letf-save--")) - (bound (and (memq (car place) '(symbol-value symbol-function)) - (gensym "--letf-bound--"))) - (temp (and (not (cl-const-expr-p value)) (cdr bindings) - (gensym "--letf-val--")))) - (setq lets (nconc (car method) - (if bound - (list (list bound - (list (if (eq (car place) - 'symbol-value) - 'boundp 'fboundp) - (nth 1 (nth 2 method)))) - (list save (list 'and bound - (nth 2 method)))) - (list (list save (nth 2 method)))) - (and temp (list (list temp value))) - lets) - body (list - (list 'unwind-protect - (cons 'progn - (if (cdr (car rev)) - (cons (cl-setf-do-store (nth 1 method) - (or temp value)) - body) - body)) - (if bound - (list 'if bound - (cl-setf-do-store (nth 1 method) save) - (list (if (eq (car place) 'symbol-value) - 'makunbound 'fmakunbound) - (nth 1 (nth 2 method)))) - (cl-setf-do-store (nth 1 method) save)))) - rev (cdr rev)))) - (list* 'let* lets body)))) - -;;;###autoload -(defmacro letf* (bindings &rest body) - "(letf* ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. -This is the analogue of `let*', but with generalized variables (in the -sense of `setf') for the PLACEs. Each PLACE is set to the corresponding -VALUE, then the BODY forms are executed. On exit, either normally or -because of a `throw' or error, the PLACEs are set back to their original -values. Note that this macro is *not* available in Common Lisp. -As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', -the PLACE is not modified before executing BODY." - (if (null bindings) - (cons 'progn body) - (setq bindings (reverse bindings)) - (while bindings - (setq body (list (list* 'letf (list (cl-pop bindings)) body)))) - (car body))) - -;;;###autoload -(defmacro callf (func place &rest args) - "(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...). -FUNC should be an unquoted function name. PLACE may be a symbol, -or any generalized variable allowed by `setf'." - (let* ((method (cl-setf-do-modify place (cons 'list args))) - (rargs (cons (nth 2 method) args))) - (list 'let* (car method) - (cl-setf-do-store (nth 1 method) - (if (symbolp func) (cons func rargs) - (list* 'funcall (list 'function func) - rargs)))))) - -;;;###autoload -(defmacro callf2 (func arg1 place &rest args) - "(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...). -Like `callf', but PLACE is the second argument of FUNC, not the first." - (if (and (cl-safe-expr-p arg1) (cl-simple-expr-p place) (symbolp func)) - (list 'setf place (list* func arg1 place args)) - (let* ((method (cl-setf-do-modify place (cons 'list args))) - (temp (and (not (cl-const-expr-p arg1)) (gensym "--arg1--"))) - (rargs (list* (or temp arg1) (nth 2 method) args))) - (list 'let* (append (and temp (list (list temp arg1))) (car method)) - (cl-setf-do-store (nth 1 method) - (if (symbolp func) (cons func rargs) - (list* 'funcall (list 'function func) - rargs))))))) - -;;;###autoload -(defmacro define-modify-macro (name arglist func &optional doc) - "(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro. -If NAME is called, it combines its PLACE argument with the other arguments -from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" - (if (memq '&key arglist) (error "&key not allowed in define-modify-macro")) - (let ((place (gensym "--place--"))) - (list 'defmacro* name (cons place arglist) doc - (list* (if (memq '&rest arglist) 'list* 'list) - '(quote callf) (list 'quote func) place - (cl-arglist-args arglist))))) - - -;;; Structures. - -;;;###autoload -(defmacro defstruct (struct &rest descs) - "(defstruct (NAME OPTIONS...) (SLOT SLOT-OPTS...)...): define a struct type. -This macro defines a new Lisp data type called NAME, which contains data -stored in SLOTs. This defines a `make-NAME' constructor, a `copy-NAME' -copier, a `NAME-p' predicate, and setf-able `NAME-SLOT' accessors." - (let* ((name (if (consp struct) (car struct) struct)) - (opts (cdr-safe struct)) - (slots nil) - (defaults nil) - (conc-name (concat (symbol-name name) "-")) - (constructor (intern (format "make-%s" name))) - (constrs nil) - (copier (intern (format "copy-%s" name))) - (predicate (intern (format "%s-p" name))) - (print-func nil) (print-auto nil) - (safety (if (cl-compiling-file) cl-optimize-safety 3)) - (include nil) - (tag (intern (format "cl-struct-%s" name))) - (tag-symbol (intern (format "cl-struct-%s-tags" name))) - (include-descs nil) - ;; XEmacs change - (include-tag-symbol nil) - (side-eff nil) - (type nil) - (named nil) - (forms nil) - pred-form pred-check) - (if (stringp (car descs)) - (cl-push (list 'put (list 'quote name) '(quote structure-documentation) - (cl-pop descs)) forms)) - (setq descs (cons '(cl-tag-slot) - (mapcar (function (lambda (x) (if (consp x) x (list x)))) - descs))) - (while opts - (let ((opt (if (consp (car opts)) (caar opts) (car opts))) - (args (cdr-safe (cl-pop opts)))) - (cond ((eq opt ':conc-name) - (if args - (setq conc-name (if (car args) - (symbol-name (car args)) "")))) - ((eq opt ':constructor) - (if (cdr args) - (cl-push args constrs) - (if args (setq constructor (car args))))) - ((eq opt ':copier) - (if args (setq copier (car args)))) - ((eq opt ':predicate) - (if args (setq predicate (car args)))) - ((eq opt ':include) - (setq include (car args) - include-descs (mapcar (function - (lambda (x) - (if (consp x) x (list x)))) - (cdr args)) - ;; XEmacs change - include-tag-symbol (intern (format "cl-struct-%s-tags" - include)))) - ((eq opt ':print-function) - (setq print-func (car args))) - ((eq opt ':type) - (setq type (car args))) - ((eq opt ':named) - (setq named t)) - ((eq opt ':initial-offset) - (setq descs (nconc (make-list (car args) '(cl-skip-slot)) - descs))) - (t - (error "Slot option %s unrecognized" opt))))) - (if print-func - (setq print-func (list 'progn - (list 'funcall (list 'function print-func) - 'cl-x 'cl-s 'cl-n) t)) - (or type (and include (not (get include 'cl-struct-print))) - (setq print-auto t - print-func (and (or (not (or include type)) (null print-func)) - (list 'progn - (list 'princ (format "#S(%s" name) - 'cl-s)))))) - (if include - (let ((inc-type (get include 'cl-struct-type)) - (old-descs (get include 'cl-struct-slots))) - (or inc-type (error "%s is not a struct name" include)) - (and type (not (eq (car inc-type) type)) - (error ":type disagrees with :include for %s" name)) - (while include-descs - (setcar (memq (or (assq (caar include-descs) old-descs) - (error "No slot %s in included struct %s" - (caar include-descs) include)) - old-descs) - (cl-pop include-descs))) - (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs)) - type (car inc-type) - named (assq 'cl-tag-slot descs)) - (if (cadr inc-type) (setq tag name named t)) - (let ((incl include)) - (while incl - (cl-push (list 'pushnew (list 'quote tag) - (intern (format "cl-struct-%s-tags" incl))) - forms) - (setq incl (get incl 'cl-struct-include))))) - (if type - (progn - (or (memq type '(vector list)) - (error "Illegal :type specifier: %s" type)) - (if named (setq tag name))) - (setq type 'vector named 'true))) - (or named (setq descs (delq (assq 'cl-tag-slot descs) descs))) - (cl-push (list 'defvar tag-symbol) forms) - (setq pred-form (and named - (let ((pos (- (length descs) - (length (memq (assq 'cl-tag-slot descs) - descs))))) - (if (eq type 'vector) - (list 'and '(vectorp cl-x) - (list '>= '(length cl-x) (length descs)) - (list 'memq (list 'aref 'cl-x pos) - tag-symbol)) - (if (= pos 0) - (list 'memq '(car-safe cl-x) tag-symbol) - (list 'and '(consp cl-x) - (list 'memq (list 'nth pos 'cl-x) - tag-symbol)))))) - pred-check (and pred-form (> safety 0) - (if (and (eq (caadr pred-form) 'vectorp) - (= safety 1)) - (cons 'and (cdddr pred-form)) pred-form))) - (let ((pos 0) (descp descs)) - (while descp - (let* ((desc (cl-pop descp)) - (slot (car desc))) - (if (memq slot '(cl-tag-slot cl-skip-slot)) - (progn - (cl-push nil slots) - (cl-push (and (eq slot 'cl-tag-slot) (list 'quote tag)) - defaults)) - (if (assq slot descp) - (error "Duplicate slots named %s in %s" slot name)) - (let ((accessor (intern (format "%s%s" conc-name slot)))) - (cl-push slot slots) - (cl-push (nth 1 desc) defaults) - (cl-push (list* - 'defsubst* accessor '(cl-x) - (append - (and pred-check - (list (list 'or pred-check - (list 'error - (format "%s accessing a non-%s" - accessor name) - 'cl-x)))) - (list (if (eq type 'vector) (list 'aref 'cl-x pos) - (if (= pos 0) '(car cl-x) - (list 'nth pos 'cl-x)))))) forms) - (cl-push (cons accessor t) side-eff) - (cl-push (list 'define-setf-method accessor '(cl-x) - (if (cadr (memq ':read-only (cddr desc))) - (list 'error (format "%s is a read-only slot" - accessor)) - (list 'cl-struct-setf-expander 'cl-x - (list 'quote name) (list 'quote accessor) - (and pred-check (list 'quote pred-check)) - pos))) - forms) - (if print-auto - (nconc print-func - (list (list 'princ (format " %s" slot) 'cl-s) - (list 'prin1 (list accessor 'cl-x) 'cl-s))))))) - (setq pos (1+ pos)))) - (setq slots (nreverse slots) - defaults (nreverse defaults)) - (and predicate pred-form - (progn (cl-push (list 'defsubst* predicate '(cl-x) - (if (eq (car pred-form) 'and) - (append pred-form '(t)) - (list 'and pred-form t))) forms) - (cl-push (cons predicate 'error-free) side-eff))) - (and copier - (progn (cl-push (list 'defun copier '(x) '(copy-sequence x)) forms) - (cl-push (cons copier t) side-eff))) - (if constructor - (cl-push (list constructor - (cons '&key (delq nil (copy-sequence slots)))) - constrs)) - (while constrs - (let* ((name (caar constrs)) - (args (cadr (cl-pop constrs))) - (anames (cl-arglist-args args)) - (make (mapcar* (function (lambda (s d) (if (memq s anames) s d))) - slots defaults))) - (cl-push (list 'defsubst* name - (list* '&cl-defs (list 'quote (cons nil descs)) args) - (cons type make)) forms) - (if (cl-safe-expr-p (cons 'progn (mapcar 'second descs))) - (cl-push (cons name t) side-eff)))) - (if print-auto (nconc print-func (list '(princ ")" cl-s) t))) - (if print-func - (cl-push (list 'push - (list 'function - (list 'lambda '(cl-x cl-s cl-n) - (list 'and pred-form print-func))) - 'custom-print-functions) forms)) - (cl-push (list 'setq tag-symbol (list 'list (list 'quote tag))) forms) - (cl-push (list* 'eval-when '(compile load eval) - (list 'put (list 'quote name) '(quote cl-struct-slots) - (list 'quote descs)) - (list 'put (list 'quote name) '(quote cl-struct-type) - (list 'quote (list type (eq named t)))) - (list 'put (list 'quote name) '(quote cl-struct-include) - (list 'quote include)) - (list 'put (list 'quote name) '(quote cl-struct-print) - print-auto) - (mapcar (function (lambda (x) - (list 'put (list 'quote (car x)) - '(quote side-effect-free) - (list 'quote (cdr x))))) - side-eff)) - forms) - (cons 'progn (nreverse (cons (list 'quote name) forms))))) - -;;;###autoload -(defun cl-struct-setf-expander (x name accessor pred-form pos) - (let* ((temp (gensym "--x--")) (store (gensym "--store--"))) - (list (list temp) (list x) (list store) - (append '(progn) - (and pred-form - (list (list 'or (subst temp 'cl-x pred-form) - (list 'error - (format - "%s storing a non-%s" accessor name) - temp)))) - (list (if (eq (car (get name 'cl-struct-type)) 'vector) - (list 'aset temp pos store) - (list 'setcar - (if (<= pos 5) - (let ((xx temp)) - (while (>= (setq pos (1- pos)) 0) - (setq xx (list 'cdr xx))) - xx) - (list 'nthcdr pos temp)) - store)))) - (list accessor temp)))) - - -;;; Types and assertions. - -;;;###autoload -(defmacro deftype (name args &rest body) - "(deftype NAME ARGLIST BODY...): define NAME as a new data type. -The type name can then be used in `typecase', `check-type', etc." - (list 'eval-when '(compile load eval) - (cl-transform-function-property - name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) args) body)))) - -(defun cl-make-type-test (val type) - (if (symbolp type) - (cond ((get type 'cl-deftype-handler) - (cl-make-type-test val (funcall (get type 'cl-deftype-handler)))) - ((memq type '(nil t)) type) - ((eq type 'string-char) (list 'characterp val)) - ((eq type 'null) (list 'null val)) - ((eq type 'float) (list 'floatp-safe val)) - ((eq type 'real) (list 'numberp val)) - ((eq type 'fixnum) (list 'integerp val)) - (t - (let* ((name (symbol-name type)) - (namep (intern (concat name "p")))) - (if (fboundp namep) (list namep val) - (list (intern (concat name "-p")) val))))) - (cond ((get (car type) 'cl-deftype-handler) - (cl-make-type-test val (apply (get (car type) 'cl-deftype-handler) - (cdr type)))) - ((memq (car-safe type) '(integer float real number)) - (delq t (list 'and (cl-make-type-test val (car type)) - (if (memq (cadr type) '(* nil)) t - (if (consp (cadr type)) (list '> val (caadr type)) - (list '>= val (cadr type)))) - (if (memq (caddr type) '(* nil)) t - (if (consp (caddr type)) (list '< val (caaddr type)) - (list '<= val (caddr type))))))) - ((memq (car-safe type) '(and or not)) - (cons (car type) - (mapcar (function (lambda (x) (cl-make-type-test val x))) - (cdr type)))) - ((memq (car-safe type) '(member member*)) - (list 'and (list 'member* val (list 'quote (cdr type))) t)) - ((eq (car-safe type) 'satisfies) (list (cadr type) val)) - (t (error "Bad type spec: %s" type))))) - -;;;###autoload -(defun typep (val type) ; See compiler macro below. - "Check that OBJECT is of type TYPE. -TYPE is a Common Lisp-style type specifier." - (eval (cl-make-type-test 'val type))) - -;;;###autoload -(defmacro check-type (form type &optional string) - "Verify that FORM is of type TYPE; signal an error if not. -STRING is an optional description of the desired type." - (and (or (not (cl-compiling-file)) - (< cl-optimize-speed 3) (= cl-optimize-safety 3)) - (let* ((temp (if (cl-simple-expr-p form 3) form (gensym))) - (body (list 'or (cl-make-type-test temp type) - (list 'signal '(quote wrong-type-argument) - (list 'list (or string (list 'quote type)) - temp (list 'quote form)))))) - (if (eq temp form) (list 'progn body nil) - (list 'let (list (list temp form)) body nil))))) - -;;;###autoload -(defmacro assert (form &optional show-args string &rest args) - "Verify that FORM returns non-nil; signal an error if not. -Second arg SHOW-ARGS means to include arguments of FORM in message. -Other args STRING and ARGS... are arguments to be passed to `error'. -They are not evaluated unless the assertion fails. If STRING is -omitted, a default message listing FORM itself is used." - (and (or (not (cl-compiling-file)) - (< cl-optimize-speed 3) (= cl-optimize-safety 3)) - (let ((sargs (and show-args (delq nil (mapcar - (function - (lambda (x) - (and (not (cl-const-expr-p x)) - x))) (cdr form)))))) - (list 'progn - (list 'or form - (if string - (list* 'error string (append sargs args)) - (list 'signal '(quote cl-assertion-failed) - (list* 'list (list 'quote form) sargs)))) - nil)))) - -;;;###autoload -(defmacro ignore-errors (&rest body) - "Execute FORMS; if an error occurs, return nil. -Otherwise, return result of last FORM." - (list 'condition-case nil (cons 'progn body) '(error nil))) - - -;;; Some predicates for analyzing Lisp forms. These are used by various -;;; macro expanders to optimize the results in certain common cases. - -(defconst cl-simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max - car-safe cdr-safe progn prog1 prog2)) -(defconst cl-safe-funcs '(* / % length memq list vector vectorp - < > <= >= = error)) - -;;; Check if no side effects, and executes quickly. -(defun cl-simple-expr-p (x &optional size) - (or size (setq size 10)) - (if (and (consp x) (not (memq (car x) '(quote function function*)))) - (and (symbolp (car x)) - (or (memq (car x) cl-simple-funcs) - (get (car x) 'side-effect-free)) - (progn - (setq size (1- size)) - (while (and (setq x (cdr x)) - (setq size (cl-simple-expr-p (car x) size)))) - (and (null x) (>= size 0) size))) - (and (> size 0) (1- size)))) - -(defun cl-simple-exprs-p (xs) - (while (and xs (cl-simple-expr-p (car xs))) - (setq xs (cdr xs))) - (not xs)) - -;;; Check if no side effects. -(defun cl-safe-expr-p (x) - (or (not (and (consp x) (not (memq (car x) '(quote function function*))))) - (and (symbolp (car x)) - (or (memq (car x) cl-simple-funcs) - (memq (car x) cl-safe-funcs) - (get (car x) 'side-effect-free)) - (progn - (while (and (setq x (cdr x)) (cl-safe-expr-p (car x)))) - (null x))))) - -;;; Check if constant (i.e., no side effects or dependencies). -(defun cl-const-expr-p (x) - (cond ((consp x) - (or (eq (car x) 'quote) - (and (memq (car x) '(function function*)) - (or (symbolp (nth 1 x)) - (and (eq (car-safe (nth 1 x)) 'lambda) 'func))))) - ((symbolp x) (and (memq x '(nil t)) t)) - (t t))) - -(defun cl-const-exprs-p (xs) - (while (and xs (cl-const-expr-p (car xs))) - (setq xs (cdr xs))) - (not xs)) - -(defun cl-const-expr-val (x) - (and (eq (cl-const-expr-p x) t) (if (consp x) (nth 1 x) x))) - -(defun cl-expr-access-order (x v) - (if (cl-const-expr-p x) v - (if (consp x) - (progn - (while (setq x (cdr x)) (setq v (cl-expr-access-order (car x) v))) - v) - (if (eq x (car v)) (cdr v) '(t))))) - -;;; Count number of times X refers to Y. Return NIL for 0 times. -(defun cl-expr-contains (x y) - (cond ((equal y x) 1) - ((and (consp x) (not (memq (car-safe x) '(quote function function*)))) - (let ((sum 0)) - (while x - (setq sum (+ sum (or (cl-expr-contains (cl-pop x) y) 0)))) - (and (> sum 0) sum))) - (t nil))) - -(defun cl-expr-contains-any (x y) - (while (and y (not (cl-expr-contains x (car y)))) (cl-pop y)) - y) - -;;; Check whether X may depend on any of the symbols in Y. -(defun cl-expr-depends-p (x y) - (and (not (cl-const-expr-p x)) - (or (not (cl-safe-expr-p x)) (cl-expr-contains-any x y)))) - - -;;; Compiler macros. - -;;;###autoload -(defmacro define-compiler-macro (func args &rest body) - "(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro. -This is like `defmacro', but macro expansion occurs only if the call to -FUNC is compiled (i.e., not interpreted). Compiler macros should be used -for optimizing the way calls to FUNC are compiled; the form returned by -BODY should do the same thing as a call to the normal function called -FUNC, though possibly more efficiently. Note that, like regular macros, -compiler macros are expanded repeatedly until no further expansions are -possible. Unlike regular macros, BODY can decide to \"punt\" and leave the -original function call alone by declaring an initial `&whole foo' parameter -and then returning foo." - (let ((p (if (listp args) args (list '&rest args))) (res nil)) - (while (consp p) (cl-push (cl-pop p) res)) - (setq args (nreverse res)) (setcdr res (and p (list '&rest p)))) - (list 'eval-when '(compile load eval) - (cl-transform-function-property - func 'cl-compiler-macro - (cons (if (memq '&whole args) (delq '&whole args) - (cons '--cl-whole-arg-- args)) body)) - (list 'or (list 'get (list 'quote func) '(quote byte-compile)) - (list 'put (list 'quote func) '(quote byte-compile) - '(quote cl-byte-compile-compiler-macro))))) - -;;;###autoload -(defun compiler-macroexpand (form) - (while - (let ((func (car-safe form)) (handler nil)) - (while (and (symbolp func) - (not (setq handler (get func 'cl-compiler-macro))) - (fboundp func) - (or (not (eq (car-safe (symbol-function func)) 'autoload)) - (load (nth 1 (symbol-function func))))) - (setq func (symbol-function func))) - (and handler - (not (eq form (setq form (apply handler form (cdr form)))))))) - form) - -(defun cl-byte-compile-compiler-macro (form) - (if (eq form (setq form (compiler-macroexpand form))) - (byte-compile-normal-call form) - (byte-compile-form form))) - -(defmacro defsubst* (name args &rest body) - "(defsubst* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. -Like `defun', except the function is automatically declared `inline', -ARGLIST allows full Common Lisp conventions, and BODY is implicitly -surrounded by (block NAME ...)." - (let* ((argns (cl-arglist-args args)) (p argns) - (pbody (cons 'progn body)) - (unsafe (not (cl-safe-expr-p pbody)))) - (while (and p (eq (cl-expr-contains args (car p)) 1)) (cl-pop p)) - (list 'progn - (if p nil ; give up if defaults refer to earlier args - (list 'define-compiler-macro name - (list* '&whole 'cl-whole '&cl-quote args) - (list* 'cl-defsubst-expand (list 'quote argns) - (list 'quote (list* 'block name body)) - (not (or unsafe (cl-expr-access-order pbody argns))) - (and (memq '&key args) 'cl-whole) unsafe argns))) - (list* 'defun* name args body)))) - -(defun cl-defsubst-expand (argns body simple whole unsafe &rest argvs) - (if (and whole (not (cl-safe-expr-p (cons 'progn argvs)))) whole - (if (cl-simple-exprs-p argvs) (setq simple t)) - (let ((lets (delq nil - (mapcar* (function - (lambda (argn argv) - (if (or simple (cl-const-expr-p argv)) - (progn (setq body (subst argv argn body)) - (and unsafe (list argn argv))) - (list argn argv)))) - argns argvs)))) - (if lets (list 'let lets body) body)))) - - -;;; Compile-time optimizations for some functions defined in this package. -;;; Note that cl.el arranges to force cl-macs to be loaded at compile-time, -;;; mainly to make sure these macros will be present. - -(put 'eql 'byte-compile nil) -(define-compiler-macro eql (&whole form a b) - (cond ((eq (cl-const-expr-p a) t) - (let ((val (cl-const-expr-val a))) - (if (and (numberp val) (not (integerp val))) - (list 'equal a b) - (list 'eq a b)))) - ((eq (cl-const-expr-p b) t) - (let ((val (cl-const-expr-val b))) - (if (and (numberp val) (not (integerp val))) - (list 'equal a b) - (list 'eq a b)))) - ((cl-simple-expr-p a 5) - (list 'if (list 'numberp a) - (list 'equal a b) - (list 'eq a b))) - ((and (cl-safe-expr-p a) - (cl-simple-expr-p b 5)) - (list 'if (list 'numberp b) - (list 'equal a b) - (list 'eq a b))) - (t form))) - -(define-compiler-macro member* (&whole form a list &rest keys) - (let ((test (and (= (length keys) 2) (eq (car keys) ':test) - (cl-const-expr-val (nth 1 keys))))) - (cond ((eq test 'eq) (list 'memq a list)) - ((eq test 'equal) (list 'member a list)) - ((or (null keys) (eq test 'eql)) - (if (eq (cl-const-expr-p a) t) - (list (if (floatp-safe (cl-const-expr-val a)) 'member 'memq) - a list) - (if (eq (cl-const-expr-p list) t) - (let ((p (cl-const-expr-val list)) (mb nil) (mq nil)) - (if (not (cdr p)) - (and p (list 'eql a (list 'quote (car p)))) - (while p - (if (floatp-safe (car p)) (setq mb t) - (or (integerp (car p)) (symbolp (car p)) (setq mq t))) - (setq p (cdr p))) - (if (not mb) (list 'memq a list) - (if (not mq) (list 'member a list) form)))) - form))) - (t form)))) - -(define-compiler-macro assoc* (&whole form a list &rest keys) - (let ((test (and (= (length keys) 2) (eq (car keys) ':test) - (cl-const-expr-val (nth 1 keys))))) - (cond ((eq test 'eq) (list 'assq a list)) - ((eq test 'equal) (list 'assoc a list)) - ((and (eq (cl-const-expr-p a) t) (or (null keys) (eq test 'eql))) - (if (floatp-safe (cl-const-expr-val a)) - (list 'assoc a list) (list 'assq a list))) - (t form)))) - -(define-compiler-macro adjoin (&whole form a list &rest keys) - (if (and (cl-simple-expr-p a) (cl-simple-expr-p list) - (not (memq ':key keys))) - (list 'if (list* 'member* a list keys) list (list 'cons a list)) - form)) - -(define-compiler-macro list* (arg &rest others) - (let* ((args (reverse (cons arg others))) - (form (car args))) - (while (setq args (cdr args)) - (setq form (list 'cons (car args) form))) - form)) - -(define-compiler-macro get* (sym prop &optional def) - (if def - (list 'getf (list 'symbol-plist sym) prop def) - (list 'get sym prop))) - -(define-compiler-macro typep (&whole form val type) - (if (cl-const-expr-p type) - (let ((res (cl-make-type-test val (cl-const-expr-val type)))) - (if (or (memq (cl-expr-contains res val) '(nil 1)) - (cl-simple-expr-p val)) res - (let ((temp (gensym))) - (list 'let (list (list temp val)) (subst temp val res))))) - form)) - - -(mapcar (function - (lambda (y) - (put (car y) 'side-effect-free t) - (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro) - (put (car y) 'cl-compiler-macro - (list 'lambda '(w x) - (if (symbolp (cadr y)) - (list 'list (list 'quote (cadr y)) - (list 'list (list 'quote (caddr y)) 'x)) - (cons 'list (cdr y))))))) - '((first 'car x) (second 'cadr x) (third 'caddr x) (fourth 'cadddr x) - (fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x) - (eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x) - (rest 'cdr x) (endp 'null x) (plusp '> x 0) (minusp '< x 0) - (caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr) - (caaar car caar) (caadr car cadr) (cadar car cdar) - (caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr) - (cddar cdr cdar) (cdddr cdr cddr) (caaaar car caaar) - (caaadr car caadr) (caadar car cadar) (caaddr car caddr) - (cadaar car cdaar) (cadadr car cdadr) (caddar car cddar) - (cadddr car cdddr) (cdaaar cdr caaar) (cdaadr cdr caadr) - (cdadar cdr cadar) (cdaddr cdr caddr) (cddaar cdr cdaar) - (cddadr cdr cdadr) (cdddar cdr cddar) (cddddr cdr cdddr) )) - -;;; Things that are inline. -(proclaim '(inline floatp-safe acons map concatenate notany notevery -;; XEmacs change - cl-set-elt revappend nreconc)) - -;;; Things that are side-effect-free. -(mapcar (function (lambda (x) (put x 'side-effect-free t))) - '(oddp evenp abs expt signum last butlast ldiff pairlis gcd lcm - isqrt floor* ceiling* truncate* round* mod* rem* subseq - list-length get* getf gethash hash-table-count)) - -;;; Things that are side-effect-and-error-free. -(mapcar (function (lambda (x) (put x 'side-effect-free 'error-free))) - '(eql floatp-safe list* subst acons equalp random-state-p - copy-tree sublis hash-table-p)) - - -(run-hooks 'cl-macs-load-hook) - -;;; cl-macs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl/cl-seq.el --- a/lisp/cl/cl-seq.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,935 +0,0 @@ -;;; cl-seq.el --- Common Lisp extensions for GNU Emacs Lisp (part three) - -;; Copyright (C) 1993 Free Software Foundation, Inc. - -;; Author: Dave Gillespie -;; Version: 2.02 -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; These are extensions to Emacs Lisp that provide a degree of -;; Common Lisp compatibility, beyond what is already built-in -;; in Emacs Lisp. -;; -;; This package was written by Dave Gillespie; it is a complete -;; rewrite of Cesar Quiroz's original cl.el package of December 1986. -;; -;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. -;; -;; Bug reports, comments, and suggestions are welcome! - -;; This file contains the Common Lisp sequence and list functions -;; which take keyword arguments. - -;; See cl.el for Change Log. - - -;;; Code: - -(or (memq 'cl-19 features) - (error "Tried to load `cl-seq' before `cl'!")) - - -;;; We define these here so that this file can compile without having -;;; loaded the cl.el file already. - -(defmacro cl-push (x place) (list 'setq place (list 'cons x place))) -(defmacro cl-pop (place) - (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) - - -;;; Keyword parsing. This is special-cased here so that we can compile -;;; this file independent from cl-macs. - -(defmacro cl-parsing-keywords (kwords other-keys &rest body) - (cons - 'let* - (cons (mapcar - (function - (lambda (x) - (let* ((var (if (consp x) (car x) x)) - (mem (list 'car (list 'cdr (list 'memq (list 'quote var) - 'cl-keys))))) - (if (eq var ':test-not) - (setq mem (list 'and mem (list 'setq 'cl-test mem) t))) - (if (eq var ':if-not) - (setq mem (list 'and mem (list 'setq 'cl-if mem) t))) - (list (intern - (format "cl-%s" (substring (symbol-name var) 1))) - (if (consp x) (list 'or mem (car (cdr x))) mem))))) - kwords) - (append - (and (not (eq other-keys t)) - (list - (list 'let '((cl-keys-temp cl-keys)) - (list 'while 'cl-keys-temp - (list 'or (list 'memq '(car cl-keys-temp) - (list 'quote - (mapcar - (function - (lambda (x) - (if (consp x) - (car x) x))) - (append kwords - other-keys)))) - '(car (cdr (memq (quote :allow-other-keys) - cl-keys))) - '(error "Bad keyword argument %s" - (car cl-keys-temp))) - '(setq cl-keys-temp (cdr (cdr cl-keys-temp))))))) - body)))) -(put 'cl-parsing-keywords 'lisp-indent-function 2) -(put 'cl-parsing-keywords 'edebug-form-spec '(sexp sexp &rest form)) - -(defmacro cl-check-key (x) - (list 'if 'cl-key (list 'funcall 'cl-key x) x)) - -(defmacro cl-check-test-nokey (item x) - (list 'cond - (list 'cl-test - (list 'eq (list 'not (list 'funcall 'cl-test item x)) - 'cl-test-not)) - (list 'cl-if - (list 'eq (list 'not (list 'funcall 'cl-if x)) 'cl-if-not)) - (list 't (list 'if (list 'numberp item) - (list 'equal item x) (list 'eq item x))))) - -(defmacro cl-check-test (item x) - (list 'cl-check-test-nokey item (list 'cl-check-key x))) - -(defmacro cl-check-match (x y) - (setq x (list 'cl-check-key x) y (list 'cl-check-key y)) - (list 'if 'cl-test - (list 'eq (list 'not (list 'funcall 'cl-test x y)) 'cl-test-not) - (list 'if (list 'numberp x) - (list 'equal x y) (list 'eq x y)))) - -(put 'cl-check-key 'edebug-form-spec 'edebug-forms) -(put 'cl-check-test 'edebug-form-spec 'edebug-forms) -(put 'cl-check-test-nokey 'edebug-form-spec 'edebug-forms) -(put 'cl-check-match 'edebug-form-spec 'edebug-forms) - -(defvar cl-test) (defvar cl-test-not) -(defvar cl-if) (defvar cl-if-not) -(defvar cl-key) - - -(defun reduce (cl-func cl-seq &rest cl-keys) - "Reduce two-argument FUNCTION across SEQUENCE. -Keywords supported: :start :end :from-end :initial-value :key" - (cl-parsing-keywords (:from-end (:start 0) :end :initial-value :key) () - (or (listp cl-seq) (setq cl-seq (append cl-seq nil))) - (setq cl-seq (subseq cl-seq cl-start cl-end)) - (if cl-from-end (setq cl-seq (nreverse cl-seq))) - (let ((cl-accum (cond ((memq ':initial-value cl-keys) cl-initial-value) - (cl-seq (cl-check-key (cl-pop cl-seq))) - (t (funcall cl-func))))) - (if cl-from-end - (while cl-seq - (setq cl-accum (funcall cl-func (cl-check-key (cl-pop cl-seq)) - cl-accum))) - (while cl-seq - (setq cl-accum (funcall cl-func cl-accum - (cl-check-key (cl-pop cl-seq)))))) - cl-accum))) - -(defun fill (seq item &rest cl-keys) - "Fill the elements of SEQ with ITEM. -Keywords supported: :start :end" - (cl-parsing-keywords ((:start 0) :end) () - (if (listp seq) - (let ((p (nthcdr cl-start seq)) - (n (if cl-end (- cl-end cl-start) 8000000))) - (while (and p (>= (setq n (1- n)) 0)) - (setcar p item) - (setq p (cdr p)))) - (or cl-end (setq cl-end (length seq))) - (if (and (= cl-start 0) (= cl-end (length seq))) - (fillarray seq item) - (while (< cl-start cl-end) - (aset seq cl-start item) - (setq cl-start (1+ cl-start))))) - seq)) - -(defun replace (cl-seq1 cl-seq2 &rest cl-keys) - "Replace the elements of SEQ1 with the elements of SEQ2. -SEQ1 is destructively modified, then returned. -Keywords supported: :start1 :end1 :start2 :end2" - (cl-parsing-keywords ((:start1 0) :end1 (:start2 0) :end2) () - (if (and (eq cl-seq1 cl-seq2) (<= cl-start2 cl-start1)) - (or (= cl-start1 cl-start2) - (let* ((cl-len (length cl-seq1)) - (cl-n (min (- (or cl-end1 cl-len) cl-start1) - (- (or cl-end2 cl-len) cl-start2)))) - (while (>= (setq cl-n (1- cl-n)) 0) - (cl-set-elt cl-seq1 (+ cl-start1 cl-n) - (elt cl-seq2 (+ cl-start2 cl-n)))))) - (if (listp cl-seq1) - (let ((cl-p1 (nthcdr cl-start1 cl-seq1)) - (cl-n1 (if cl-end1 (- cl-end1 cl-start1) 4000000))) - (if (listp cl-seq2) - (let ((cl-p2 (nthcdr cl-start2 cl-seq2)) - (cl-n (min cl-n1 - (if cl-end2 (- cl-end2 cl-start2) 4000000)))) - (while (and cl-p1 cl-p2 (>= (setq cl-n (1- cl-n)) 0)) - (setcar cl-p1 (car cl-p2)) - (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))) - (setq cl-end2 (min (or cl-end2 (length cl-seq2)) - (+ cl-start2 cl-n1))) - (while (and cl-p1 (< cl-start2 cl-end2)) - (setcar cl-p1 (aref cl-seq2 cl-start2)) - (setq cl-p1 (cdr cl-p1) cl-start2 (1+ cl-start2))))) - (setq cl-end1 (min (or cl-end1 (length cl-seq1)) - (+ cl-start1 (- (or cl-end2 (length cl-seq2)) - cl-start2)))) - (if (listp cl-seq2) - (let ((cl-p2 (nthcdr cl-start2 cl-seq2))) - (while (< cl-start1 cl-end1) - (aset cl-seq1 cl-start1 (car cl-p2)) - (setq cl-p2 (cdr cl-p2) cl-start1 (1+ cl-start1)))) - (while (< cl-start1 cl-end1) - (aset cl-seq1 cl-start1 (aref cl-seq2 cl-start2)) - (setq cl-start2 (1+ cl-start2) cl-start1 (1+ cl-start1)))))) - cl-seq1)) - -(defun remove* (cl-item cl-seq &rest cl-keys) - "Remove all occurrences of ITEM in SEQ. -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Keywords supported: :test :test-not :key :count :start :end :from-end" - (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end - (:start 0) :end) () - (if (<= (or cl-count (setq cl-count 8000000)) 0) - cl-seq - (if (or (nlistp cl-seq) (and cl-from-end (< cl-count 4000000))) - (let ((cl-i (cl-position cl-item cl-seq cl-start cl-end - cl-from-end))) - (if cl-i - (let ((cl-res (apply 'delete* cl-item (append cl-seq nil) - (append (if cl-from-end - (list ':end (1+ cl-i)) - (list ':start cl-i)) - cl-keys)))) - (if (listp cl-seq) cl-res - (if (stringp cl-seq) (concat cl-res) (vconcat cl-res)))) - cl-seq)) - (setq cl-end (- (or cl-end 8000000) cl-start)) - (if (= cl-start 0) - (while (and cl-seq (> cl-end 0) - (cl-check-test cl-item (car cl-seq)) - (setq cl-end (1- cl-end) cl-seq (cdr cl-seq)) - (> (setq cl-count (1- cl-count)) 0)))) - (if (and (> cl-count 0) (> cl-end 0)) - (let ((cl-p (if (> cl-start 0) (nthcdr cl-start cl-seq) - (setq cl-end (1- cl-end)) (cdr cl-seq)))) - (while (and cl-p (> cl-end 0) - (not (cl-check-test cl-item (car cl-p)))) - (setq cl-p (cdr cl-p) cl-end (1- cl-end))) - (if (and cl-p (> cl-end 0)) - (nconc (ldiff cl-seq cl-p) - (if (= cl-count 1) (cdr cl-p) - (and (cdr cl-p) - (apply 'delete* cl-item - (copy-sequence (cdr cl-p)) - ':start 0 ':end (1- cl-end) - ':count (1- cl-count) cl-keys)))) - cl-seq)) - cl-seq))))) - -(defun remove-if (cl-pred cl-list &rest cl-keys) - "Remove all items satisfying PREDICATE in SEQ. -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Keywords supported: :key :count :start :end :from-end" - (apply 'remove* nil cl-list ':if cl-pred cl-keys)) - -(defun remove-if-not (cl-pred cl-list &rest cl-keys) - "Remove all items not satisfying PREDICATE in SEQ. -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Keywords supported: :key :count :start :end :from-end" - (apply 'remove* nil cl-list ':if-not cl-pred cl-keys)) - -(defun delete* (cl-item cl-seq &rest cl-keys) - "Remove all occurrences of ITEM in SEQ. -This is a destructive function; it reuses the storage of SEQ whenever possible. -Keywords supported: :test :test-not :key :count :start :end :from-end" - (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end - (:start 0) :end) () - (if (<= (or cl-count (setq cl-count 8000000)) 0) - cl-seq - (if (listp cl-seq) - (if (and cl-from-end (< cl-count 4000000)) - (let (cl-i) - (while (and (>= (setq cl-count (1- cl-count)) 0) - (setq cl-i (cl-position cl-item cl-seq cl-start - cl-end cl-from-end))) - (if (= cl-i 0) (setq cl-seq (cdr cl-seq)) - (let ((cl-tail (nthcdr (1- cl-i) cl-seq))) - (setcdr cl-tail (cdr (cdr cl-tail))))) - (setq cl-end cl-i)) - cl-seq) - (setq cl-end (- (or cl-end 8000000) cl-start)) - (if (= cl-start 0) - (progn - (while (and cl-seq - (> cl-end 0) - (cl-check-test cl-item (car cl-seq)) - (setq cl-end (1- cl-end) cl-seq (cdr cl-seq)) - (> (setq cl-count (1- cl-count)) 0))) - (setq cl-end (1- cl-end))) - (setq cl-start (1- cl-start))) - (if (and (> cl-count 0) (> cl-end 0)) - (let ((cl-p (nthcdr cl-start cl-seq))) - (while (and (cdr cl-p) (> cl-end 0)) - (if (cl-check-test cl-item (car (cdr cl-p))) - (progn - (setcdr cl-p (cdr (cdr cl-p))) - (if (= (setq cl-count (1- cl-count)) 0) - (setq cl-end 1))) - (setq cl-p (cdr cl-p))) - (setq cl-end (1- cl-end))))) - cl-seq) - (apply 'remove* cl-item cl-seq cl-keys))))) - -(defun delete-if (cl-pred cl-list &rest cl-keys) - "Remove all items satisfying PREDICATE in SEQ. -This is a destructive function; it reuses the storage of SEQ whenever possible. -Keywords supported: :key :count :start :end :from-end" - (apply 'delete* nil cl-list ':if cl-pred cl-keys)) - -(defun delete-if-not (cl-pred cl-list &rest cl-keys) - "Remove all items not satisfying PREDICATE in SEQ. -This is a destructive function; it reuses the storage of SEQ whenever possible. -Keywords supported: :key :count :start :end :from-end" - (apply 'delete* nil cl-list ':if-not cl-pred cl-keys)) - -(or (and (fboundp 'delete) (subrp (symbol-function 'delete))) - (defalias 'delete (function (lambda (x y) (delete* x y ':test 'equal))))) - -(defun remove (cl-item cl-seq) - "Remove all occurrences of ITEM in SEQ, testing with `equal' -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Also see: `remove*', `delete', `delete*'" - (remove* cl-item cl-seq ':test 'equal)) - -(defun remq (cl-elt cl-list) - "Remove all occurances of ELT in LIST, comparing with `eq'. -This is a non-destructive function; it makes a copy of LIST to avoid -corrupting the original LIST. -Also see: `delq', `delete', `delete*', `remove', `remove*'." - (if (memq cl-elt cl-list) - (delq cl-elt (copy-list cl-list)) - cl-list)) - -(defun remove-duplicates (cl-seq &rest cl-keys) - "Return a copy of SEQ with all duplicate elements removed. -Keywords supported: :test :test-not :key :start :end :from-end" - (cl-delete-duplicates cl-seq cl-keys t)) - -(defun delete-duplicates (cl-seq &rest cl-keys) - "Remove all duplicate elements from SEQ (destructively). -Keywords supported: :test :test-not :key :start :end :from-end" - (cl-delete-duplicates cl-seq cl-keys nil)) - -(defun cl-delete-duplicates (cl-seq cl-keys cl-copy) - (if (listp cl-seq) - (cl-parsing-keywords (:test :test-not :key (:start 0) :end :from-end :if) - () - (if cl-from-end - (let ((cl-p (nthcdr cl-start cl-seq)) cl-i) - (setq cl-end (- (or cl-end (length cl-seq)) cl-start)) - (while (> cl-end 1) - (setq cl-i 0) - (while (setq cl-i (cl-position (cl-check-key (car cl-p)) - (cdr cl-p) cl-i (1- cl-end))) - (if cl-copy (setq cl-seq (copy-sequence cl-seq) - cl-p (nthcdr cl-start cl-seq) cl-copy nil)) - (let ((cl-tail (nthcdr cl-i cl-p))) - (setcdr cl-tail (cdr (cdr cl-tail)))) - (setq cl-end (1- cl-end))) - (setq cl-p (cdr cl-p) cl-end (1- cl-end) - cl-start (1+ cl-start))) - cl-seq) - (setq cl-end (- (or cl-end (length cl-seq)) cl-start)) - (while (and (cdr cl-seq) (= cl-start 0) (> cl-end 1) - (cl-position (cl-check-key (car cl-seq)) - (cdr cl-seq) 0 (1- cl-end))) - (setq cl-seq (cdr cl-seq) cl-end (1- cl-end))) - (let ((cl-p (if (> cl-start 0) (nthcdr (1- cl-start) cl-seq) - (setq cl-end (1- cl-end) cl-start 1) cl-seq))) - (while (and (cdr (cdr cl-p)) (> cl-end 1)) - (if (cl-position (cl-check-key (car (cdr cl-p))) - (cdr (cdr cl-p)) 0 (1- cl-end)) - (progn - (if cl-copy (setq cl-seq (copy-sequence cl-seq) - cl-p (nthcdr (1- cl-start) cl-seq) - cl-copy nil)) - (setcdr cl-p (cdr (cdr cl-p)))) - (setq cl-p (cdr cl-p))) - (setq cl-end (1- cl-end) cl-start (1+ cl-start))) - cl-seq))) - (let ((cl-res (cl-delete-duplicates (append cl-seq nil) cl-keys nil))) - (if (stringp cl-seq) (concat cl-res) (vconcat cl-res))))) - -(defun substitute (cl-new cl-old cl-seq &rest cl-keys) - "Substitute NEW for OLD in SEQ. -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Keywords supported: :test :test-not :key :count :start :end :from-end" - (cl-parsing-keywords (:test :test-not :key :if :if-not :count - (:start 0) :end :from-end) () - (if (or (eq cl-old cl-new) - (<= (or cl-count (setq cl-from-end nil cl-count 8000000)) 0)) - cl-seq - (let ((cl-i (cl-position cl-old cl-seq cl-start cl-end))) - (if (not cl-i) - cl-seq - (setq cl-seq (copy-sequence cl-seq)) - (or cl-from-end - (progn (cl-set-elt cl-seq cl-i cl-new) - (setq cl-i (1+ cl-i) cl-count (1- cl-count)))) - (apply 'nsubstitute cl-new cl-old cl-seq ':count cl-count - ':start cl-i cl-keys)))))) - -(defun substitute-if (cl-new cl-pred cl-list &rest cl-keys) - "Substitute NEW for all items satisfying PREDICATE in SEQ. -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Keywords supported: :key :count :start :end :from-end" - (apply 'substitute cl-new nil cl-list ':if cl-pred cl-keys)) - -(defun substitute-if-not (cl-new cl-pred cl-list &rest cl-keys) - "Substitute NEW for all items not satisfying PREDICATE in SEQ. -This is a non-destructive function; it makes a copy of SEQ if necessary -to avoid corrupting the original SEQ. -Keywords supported: :key :count :start :end :from-end" - (apply 'substitute cl-new nil cl-list ':if-not cl-pred cl-keys)) - -(defun nsubstitute (cl-new cl-old cl-seq &rest cl-keys) - "Substitute NEW for OLD in SEQ. -This is a destructive function; it reuses the storage of SEQ whenever possible. -Keywords supported: :test :test-not :key :count :start :end :from-end" - (cl-parsing-keywords (:test :test-not :key :if :if-not :count - (:start 0) :end :from-end) () - (or (eq cl-old cl-new) (<= (or cl-count (setq cl-count 8000000)) 0) - (if (and (listp cl-seq) (or (not cl-from-end) (> cl-count 4000000))) - (let ((cl-p (nthcdr cl-start cl-seq))) - (setq cl-end (- (or cl-end 8000000) cl-start)) - (while (and cl-p (> cl-end 0) (> cl-count 0)) - (if (cl-check-test cl-old (car cl-p)) - (progn - (setcar cl-p cl-new) - (setq cl-count (1- cl-count)))) - (setq cl-p (cdr cl-p) cl-end (1- cl-end)))) - (or cl-end (setq cl-end (length cl-seq))) - (if cl-from-end - (while (and (< cl-start cl-end) (> cl-count 0)) - (setq cl-end (1- cl-end)) - (if (cl-check-test cl-old (elt cl-seq cl-end)) - (progn - (cl-set-elt cl-seq cl-end cl-new) - (setq cl-count (1- cl-count))))) - (while (and (< cl-start cl-end) (> cl-count 0)) - (if (cl-check-test cl-old (aref cl-seq cl-start)) - (progn - (aset cl-seq cl-start cl-new) - (setq cl-count (1- cl-count)))) - (setq cl-start (1+ cl-start)))))) - cl-seq)) - -(defun nsubstitute-if (cl-new cl-pred cl-list &rest cl-keys) - "Substitute NEW for all items satisfying PREDICATE in SEQ. -This is a destructive function; it reuses the storage of SEQ whenever possible. -Keywords supported: :key :count :start :end :from-end" - (apply 'nsubstitute cl-new nil cl-list ':if cl-pred cl-keys)) - -(defun nsubstitute-if-not (cl-new cl-pred cl-list &rest cl-keys) - "Substitute NEW for all items not satisfying PREDICATE in SEQ. -This is a destructive function; it reuses the storage of SEQ whenever possible. -Keywords supported: :key :count :start :end :from-end" - (apply 'nsubstitute cl-new nil cl-list ':if-not cl-pred cl-keys)) - -(defun find (cl-item cl-seq &rest cl-keys) - "Find the first occurrence of ITEM in LIST. -Return the matching ITEM, or nil if not found. -Keywords supported: :test :test-not :key :start :end :from-end" - (let ((cl-pos (apply 'position cl-item cl-seq cl-keys))) - (and cl-pos (elt cl-seq cl-pos)))) - -(defun find-if (cl-pred cl-list &rest cl-keys) - "Find the first item satisfying PREDICATE in LIST. -Return the matching ITEM, or nil if not found. -Keywords supported: :key :start :end :from-end" - (apply 'find nil cl-list ':if cl-pred cl-keys)) - -(defun find-if-not (cl-pred cl-list &rest cl-keys) - "Find the first item not satisfying PREDICATE in LIST. -Return the matching ITEM, or nil if not found. -Keywords supported: :key :start :end :from-end" - (apply 'find nil cl-list ':if-not cl-pred cl-keys)) - -(defun position (cl-item cl-seq &rest cl-keys) - "Find the first occurrence of ITEM in LIST. -Return the index of the matching item, or nil if not found. -Keywords supported: :test :test-not :key :start :end :from-end" - (cl-parsing-keywords (:test :test-not :key :if :if-not - (:start 0) :end :from-end) () - (cl-position cl-item cl-seq cl-start cl-end cl-from-end))) - -(defun cl-position (cl-item cl-seq cl-start &optional cl-end cl-from-end) - (if (listp cl-seq) - (let ((cl-p (nthcdr cl-start cl-seq))) - (or cl-end (setq cl-end 8000000)) - (let ((cl-res nil)) - (while (and cl-p (< cl-start cl-end) (or (not cl-res) cl-from-end)) - (if (cl-check-test cl-item (car cl-p)) - (setq cl-res cl-start)) - (setq cl-p (cdr cl-p) cl-start (1+ cl-start))) - cl-res)) - (or cl-end (setq cl-end (length cl-seq))) - (if cl-from-end - (progn - (while (and (>= (setq cl-end (1- cl-end)) cl-start) - (not (cl-check-test cl-item (aref cl-seq cl-end))))) - (and (>= cl-end cl-start) cl-end)) - (while (and (< cl-start cl-end) - (not (cl-check-test cl-item (aref cl-seq cl-start)))) - (setq cl-start (1+ cl-start))) - (and (< cl-start cl-end) cl-start)))) - -(defun position-if (cl-pred cl-list &rest cl-keys) - "Find the first item satisfying PREDICATE in LIST. -Return the index of the matching item, or nil if not found. -Keywords supported: :key :start :end :from-end" - (apply 'position nil cl-list ':if cl-pred cl-keys)) - -(defun position-if-not (cl-pred cl-list &rest cl-keys) - "Find the first item not satisfying PREDICATE in LIST. -Return the index of the matching item, or nil if not found. -Keywords supported: :key :start :end :from-end" - (apply 'position nil cl-list ':if-not cl-pred cl-keys)) - -(defun count (cl-item cl-seq &rest cl-keys) - "Count the number of occurrences of ITEM in LIST. -Keywords supported: :test :test-not :key :start :end" - (cl-parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end) () - (let ((cl-count 0) cl-x) - (or cl-end (setq cl-end (length cl-seq))) - (if (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq))) - (while (< cl-start cl-end) - (setq cl-x (if (consp cl-seq) (cl-pop cl-seq) (aref cl-seq cl-start))) - (if (cl-check-test cl-item cl-x) (setq cl-count (1+ cl-count))) - (setq cl-start (1+ cl-start))) - cl-count))) - -(defun count-if (cl-pred cl-list &rest cl-keys) - "Count the number of items satisfying PREDICATE in LIST. -Keywords supported: :key :start :end" - (apply 'count nil cl-list ':if cl-pred cl-keys)) - -(defun count-if-not (cl-pred cl-list &rest cl-keys) - "Count the number of items not satisfying PREDICATE in LIST. -Keywords supported: :key :start :end" - (apply 'count nil cl-list ':if-not cl-pred cl-keys)) - -(defun mismatch (cl-seq1 cl-seq2 &rest cl-keys) - "Compare SEQ1 with SEQ2, return index of first mismatching element. -Return nil if the sequences match. If one sequence is a prefix of the -other, the return value indicates the end of the shorted sequence. -Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end" - (cl-parsing-keywords (:test :test-not :key :from-end - (:start1 0) :end1 (:start2 0) :end2) () - (or cl-end1 (setq cl-end1 (length cl-seq1))) - (or cl-end2 (setq cl-end2 (length cl-seq2))) - (if cl-from-end - (progn - (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2) - (cl-check-match (elt cl-seq1 (1- cl-end1)) - (elt cl-seq2 (1- cl-end2)))) - (setq cl-end1 (1- cl-end1) cl-end2 (1- cl-end2))) - (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2)) - (1- cl-end1))) - (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1))) - (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2)))) - (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2) - (cl-check-match (if cl-p1 (car cl-p1) - (aref cl-seq1 cl-start1)) - (if cl-p2 (car cl-p2) - (aref cl-seq2 cl-start2)))) - (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2) - cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2))) - (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2)) - cl-start1))))) - -(defun search (cl-seq1 cl-seq2 &rest cl-keys) - "Search for SEQ1 as a subsequence of SEQ2. -Return the index of the leftmost element of the first match found; -return nil if there are no matches. -Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end" - (cl-parsing-keywords (:test :test-not :key :from-end - (:start1 0) :end1 (:start2 0) :end2) () - (or cl-end1 (setq cl-end1 (length cl-seq1))) - (or cl-end2 (setq cl-end2 (length cl-seq2))) - (if (>= cl-start1 cl-end1) - (if cl-from-end cl-end2 cl-start2) - (let* ((cl-len (- cl-end1 cl-start1)) - (cl-first (cl-check-key (elt cl-seq1 cl-start1))) - (cl-if nil) cl-pos) - (setq cl-end2 (- cl-end2 (1- cl-len))) - (while (and (< cl-start2 cl-end2) - (setq cl-pos (cl-position cl-first cl-seq2 - cl-start2 cl-end2 cl-from-end)) - (apply 'mismatch cl-seq1 cl-seq2 - ':start1 (1+ cl-start1) ':end1 cl-end1 - ':start2 (1+ cl-pos) ':end2 (+ cl-pos cl-len) - ':from-end nil cl-keys)) - (if cl-from-end (setq cl-end2 cl-pos) (setq cl-start2 (1+ cl-pos)))) - (and (< cl-start2 cl-end2) cl-pos))))) - -(defun sort* (cl-seq cl-pred &rest cl-keys) - "Sort the argument SEQUENCE according to PREDICATE. -This is a destructive function; it reuses the storage of SEQUENCE if possible. -Keywords supported: :key" - (if (nlistp cl-seq) - (replace cl-seq (apply 'sort* (append cl-seq nil) cl-pred cl-keys)) - (cl-parsing-keywords (:key) () - (if (memq cl-key '(nil identity)) - (sort cl-seq cl-pred) - (sort cl-seq (function (lambda (cl-x cl-y) - (funcall cl-pred (funcall cl-key cl-x) - (funcall cl-key cl-y))))))))) - -(defun stable-sort (cl-seq cl-pred &rest cl-keys) - "Sort the argument SEQUENCE stably according to PREDICATE. -This is a destructive function; it reuses the storage of SEQUENCE if possible. -Keywords supported: :key" - (apply 'sort* cl-seq cl-pred cl-keys)) - -(defun merge (cl-type cl-seq1 cl-seq2 cl-pred &rest cl-keys) - "Destructively merge the two sequences to produce a new sequence. -TYPE is the sequence type to return, SEQ1 and SEQ2 are the two -argument sequences, and PRED is a `less-than' predicate on the elements. -Keywords supported: :key" - (or (listp cl-seq1) (setq cl-seq1 (append cl-seq1 nil))) - (or (listp cl-seq2) (setq cl-seq2 (append cl-seq2 nil))) - (cl-parsing-keywords (:key) () - (let ((cl-res nil)) - (while (and cl-seq1 cl-seq2) - (if (funcall cl-pred (cl-check-key (car cl-seq2)) - (cl-check-key (car cl-seq1))) - (cl-push (cl-pop cl-seq2) cl-res) - (cl-push (cl-pop cl-seq1) cl-res))) - (coerce (nconc (nreverse cl-res) cl-seq1 cl-seq2) cl-type)))) - -;;; See compiler macro in cl-macs.el -(defun member* (cl-item cl-list &rest cl-keys) - "Find the first occurrence of ITEM in LIST. -Return the sublist of LIST whose car is ITEM. -Keywords supported: :test :test-not :key" - (if cl-keys - (cl-parsing-keywords (:test :test-not :key :if :if-not) () - (while (and cl-list (not (cl-check-test cl-item (car cl-list)))) - (setq cl-list (cdr cl-list))) - cl-list) - (if (and (numberp cl-item) (not (integerp cl-item))) - (member cl-item cl-list) - (memq cl-item cl-list)))) - -(defun member-if (cl-pred cl-list &rest cl-keys) - "Find the first item satisfying PREDICATE in LIST. -Return the sublist of LIST whose car matches. -Keywords supported: :key" - (apply 'member* nil cl-list ':if cl-pred cl-keys)) - -(defun member-if-not (cl-pred cl-list &rest cl-keys) - "Find the first item not satisfying PREDICATE in LIST. -Return the sublist of LIST whose car matches. -Keywords supported: :key" - (apply 'member* nil cl-list ':if-not cl-pred cl-keys)) - -(defun cl-adjoin (cl-item cl-list &rest cl-keys) - (if (cl-parsing-keywords (:key) t - (apply 'member* (cl-check-key cl-item) cl-list cl-keys)) - cl-list - (cons cl-item cl-list))) - -;;; See compiler macro in cl-macs.el -(defun assoc* (cl-item cl-alist &rest cl-keys) - "Find the first item whose car matches ITEM in LIST. -Keywords supported: :test :test-not :key" - (if cl-keys - (cl-parsing-keywords (:test :test-not :key :if :if-not) () - (while (and cl-alist - (or (not (consp (car cl-alist))) - (not (cl-check-test cl-item (car (car cl-alist)))))) - (setq cl-alist (cdr cl-alist))) - (and cl-alist (car cl-alist))) - (if (and (numberp cl-item) (not (integerp cl-item))) - (assoc cl-item cl-alist) - (assq cl-item cl-alist)))) - -(defun assoc-if (cl-pred cl-list &rest cl-keys) - "Find the first item whose car satisfies PREDICATE in LIST. -Keywords supported: :key" - (apply 'assoc* nil cl-list ':if cl-pred cl-keys)) - -(defun assoc-if-not (cl-pred cl-list &rest cl-keys) - "Find the first item whose car does not satisfy PREDICATE in LIST. -Keywords supported: :key" - (apply 'assoc* nil cl-list ':if-not cl-pred cl-keys)) - -(defun rassoc* (cl-item cl-alist &rest cl-keys) - "Find the first item whose cdr matches ITEM in LIST. -Keywords supported: :test :test-not :key" - (if (or cl-keys (numberp cl-item)) - (cl-parsing-keywords (:test :test-not :key :if :if-not) () - (while (and cl-alist - (or (not (consp (car cl-alist))) - (not (cl-check-test cl-item (cdr (car cl-alist)))))) - (setq cl-alist (cdr cl-alist))) - (and cl-alist (car cl-alist))) - (rassq cl-item cl-alist))) - -(defun rassoc-if (cl-pred cl-list &rest cl-keys) - "Find the first item whose cdr satisfies PREDICATE in LIST. -Keywords supported: :key" - (apply 'rassoc* nil cl-list ':if cl-pred cl-keys)) - -(defun rassoc-if-not (cl-pred cl-list &rest cl-keys) - "Find the first item whose cdr does not satisfy PREDICATE in LIST. -Keywords supported: :key" - (apply 'rassoc* nil cl-list ':if-not cl-pred cl-keys)) - -(defun union (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-union operation. -The result list contains all items that appear in either LIST1 or LIST2. -This is a non-destructive function; it makes a copy of the data if necessary -to avoid corrupting the original LIST1 and LIST2. -Keywords supported: :test :test-not :key" - (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) - ((equal cl-list1 cl-list2) cl-list1) - (t - (or (>= (length cl-list1) (length cl-list2)) - (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1)))) - (while cl-list2 - (if (or cl-keys (numberp (car cl-list2))) - (setq cl-list1 (apply 'adjoin (car cl-list2) cl-list1 cl-keys)) - (or (memq (car cl-list2) cl-list1) - (cl-push (car cl-list2) cl-list1))) - (cl-pop cl-list2)) - cl-list1))) - -(defun nunion (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-union operation. -The result list contains all items that appear in either LIST1 or LIST2. -This is a destructive function; it reuses the storage of LIST1 and LIST2 -whenever possible. -Keywords supported: :test :test-not :key" - (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) - (t (apply 'union cl-list1 cl-list2 cl-keys)))) - -(defun intersection (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-intersection operation. -The result list contains all items that appear in both LIST1 and LIST2. -This is a non-destructive function; it makes a copy of the data if necessary -to avoid corrupting the original LIST1 and LIST2. -Keywords supported: :test :test-not :key" - (and cl-list1 cl-list2 - (if (equal cl-list1 cl-list2) cl-list1 - (cl-parsing-keywords (:key) (:test :test-not) - (let ((cl-res nil)) - (or (>= (length cl-list1) (length cl-list2)) - (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1)))) - (while cl-list2 - (if (if (or cl-keys (numberp (car cl-list2))) - (apply 'member* (cl-check-key (car cl-list2)) - cl-list1 cl-keys) - (memq (car cl-list2) cl-list1)) - (cl-push (car cl-list2) cl-res)) - (cl-pop cl-list2)) - cl-res))))) - -(defun nintersection (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-intersection operation. -The result list contains all items that appear in both LIST1 and LIST2. -This is a destructive function; it reuses the storage of LIST1 and LIST2 -whenever possible. -Keywords supported: :test :test-not :key" - (and cl-list1 cl-list2 (apply 'intersection cl-list1 cl-list2 cl-keys))) - -(defun set-difference (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-difference operation. -The result list contains all items that appear in LIST1 but not LIST2. -This is a non-destructive function; it makes a copy of the data if necessary -to avoid corrupting the original LIST1 and LIST2. -Keywords supported: :test :test-not :key" - (if (or (null cl-list1) (null cl-list2)) cl-list1 - (cl-parsing-keywords (:key) (:test :test-not) - (let ((cl-res nil)) - (while cl-list1 - (or (if (or cl-keys (numberp (car cl-list1))) - (apply 'member* (cl-check-key (car cl-list1)) - cl-list2 cl-keys) - (memq (car cl-list1) cl-list2)) - (cl-push (car cl-list1) cl-res)) - (cl-pop cl-list1)) - cl-res)))) - -(defun nset-difference (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-difference operation. -The result list contains all items that appear in LIST1 but not LIST2. -This is a destructive function; it reuses the storage of LIST1 and LIST2 -whenever possible. -Keywords supported: :test :test-not :key" - (if (or (null cl-list1) (null cl-list2)) cl-list1 - (apply 'set-difference cl-list1 cl-list2 cl-keys))) - -(defun set-exclusive-or (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-exclusive-or operation. -The result list contains all items that appear in exactly one of LIST1, LIST2. -This is a non-destructive function; it makes a copy of the data if necessary -to avoid corrupting the original LIST1 and LIST2. -Keywords supported: :test :test-not :key" - (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) - ((equal cl-list1 cl-list2) nil) - (t (append (apply 'set-difference cl-list1 cl-list2 cl-keys) - (apply 'set-difference cl-list2 cl-list1 cl-keys))))) - -(defun nset-exclusive-or (cl-list1 cl-list2 &rest cl-keys) - "Combine LIST1 and LIST2 using a set-exclusive-or operation. -The result list contains all items that appear in exactly one of LIST1, LIST2. -This is a destructive function; it reuses the storage of LIST1 and LIST2 -whenever possible. -Keywords supported: :test :test-not :key" - (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) - ((equal cl-list1 cl-list2) nil) - (t (nconc (apply 'nset-difference cl-list1 cl-list2 cl-keys) - (apply 'nset-difference cl-list2 cl-list1 cl-keys))))) - -(defun subsetp (cl-list1 cl-list2 &rest cl-keys) - "True if LIST1 is a subset of LIST2. -I.e., if every element of LIST1 also appears in LIST2. -Keywords supported: :test :test-not :key" - (cond ((null cl-list1) t) ((null cl-list2) nil) - ((equal cl-list1 cl-list2) t) - (t (cl-parsing-keywords (:key) (:test :test-not) - (while (and cl-list1 - (apply 'member* (cl-check-key (car cl-list1)) - cl-list2 cl-keys)) - (cl-pop cl-list1)) - (null cl-list1))))) - -(defun subst-if (cl-new cl-pred cl-tree &rest cl-keys) - "Substitute NEW for elements matching PREDICATE in TREE (non-destructively). -Return a copy of TREE with all matching elements replaced by NEW. -Keywords supported: :key" - (apply 'sublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys)) - -(defun subst-if-not (cl-new cl-pred cl-tree &rest cl-keys) - "Substitute NEW for elts not matching PREDICATE in TREE (non-destructively). -Return a copy of TREE with all non-matching elements replaced by NEW. -Keywords supported: :key" - (apply 'sublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys)) - -(defun nsubst (cl-new cl-old cl-tree &rest cl-keys) - "Substitute NEW for OLD everywhere in TREE (destructively). -Any element of TREE which is `eql' to OLD is changed to NEW (via a call -to `setcar'). -Keywords supported: :test :test-not :key" - (apply 'nsublis (list (cons cl-old cl-new)) cl-tree cl-keys)) - -(defun nsubst-if (cl-new cl-pred cl-tree &rest cl-keys) - "Substitute NEW for elements matching PREDICATE in TREE (destructively). -Any element of TREE which matches is changed to NEW (via a call to `setcar'). -Keywords supported: :key" - (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys)) - -(defun nsubst-if-not (cl-new cl-pred cl-tree &rest cl-keys) - "Substitute NEW for elements not matching PREDICATE in TREE (destructively). -Any element of TREE which matches is changed to NEW (via a call to `setcar'). -Keywords supported: :key" - (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys)) - -(defun sublis (cl-alist cl-tree &rest cl-keys) - "Perform substitutions indicated by ALIST in TREE (non-destructively). -Return a copy of TREE with all matching elements replaced. -Keywords supported: :test :test-not :key" - (cl-parsing-keywords (:test :test-not :key :if :if-not) () - (cl-sublis-rec cl-tree))) - -(defvar cl-alist) -(defun cl-sublis-rec (cl-tree) ; uses cl-alist/key/test*/if* - (let ((cl-temp (cl-check-key cl-tree)) (cl-p cl-alist)) - (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) - (setq cl-p (cdr cl-p))) - (if cl-p (cdr (car cl-p)) - (if (consp cl-tree) - (let ((cl-a (cl-sublis-rec (car cl-tree))) - (cl-d (cl-sublis-rec (cdr cl-tree)))) - (if (and (eq cl-a (car cl-tree)) (eq cl-d (cdr cl-tree))) - cl-tree - (cons cl-a cl-d))) - cl-tree)))) - -(defun nsublis (cl-alist cl-tree &rest cl-keys) - "Perform substitutions indicated by ALIST in TREE (destructively). -Any matching element of TREE is changed via a call to `setcar'. -Keywords supported: :test :test-not :key" - (cl-parsing-keywords (:test :test-not :key :if :if-not) () - (let ((cl-hold (list cl-tree))) - (cl-nsublis-rec cl-hold) - (car cl-hold)))) - -(defun cl-nsublis-rec (cl-tree) ; uses cl-alist/temp/p/key/test*/if* - (while (consp cl-tree) - (let ((cl-temp (cl-check-key (car cl-tree))) (cl-p cl-alist)) - (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) - (setq cl-p (cdr cl-p))) - (if cl-p (setcar cl-tree (cdr (car cl-p))) - (if (consp (car cl-tree)) (cl-nsublis-rec (car cl-tree)))) - (setq cl-temp (cl-check-key (cdr cl-tree)) cl-p cl-alist) - (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) - (setq cl-p (cdr cl-p))) - (if cl-p - (progn (setcdr cl-tree (cdr (car cl-p))) (setq cl-tree nil)) - (setq cl-tree (cdr cl-tree)))))) - -(defun tree-equal (cl-x cl-y &rest cl-keys) - "T if trees X and Y have `eql' leaves. -Atoms are compared by `eql'; cons cells are compared recursively. -Keywords supported: :test :test-not :key" - (cl-parsing-keywords (:test :test-not :key) () - (cl-tree-equal-rec cl-x cl-y))) - -(defun cl-tree-equal-rec (cl-x cl-y) - (while (and (consp cl-x) (consp cl-y) - (cl-tree-equal-rec (car cl-x) (car cl-y))) - (setq cl-x (cdr cl-x) cl-y (cdr cl-y))) - (and (not (consp cl-x)) (not (consp cl-y)) (cl-check-match cl-x cl-y))) - - -(run-hooks 'cl-seq-load-hook) - -;;; cl-seq.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cl/cl.el --- a/lisp/cl/cl.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,736 +0,0 @@ -;;; cl.el --- Common Lisp extensions for GNU Emacs Lisp - -;; Copyright (C) 1993 Free Software Foundation, Inc. - -;; Author: Dave Gillespie -;; Version: 2.02 -;; Keywords: extensions, lisp - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; These are extensions to Emacs Lisp that provide a degree of -;; Common Lisp compatibility, beyond what is already built-in -;; in Emacs Lisp. -;; -;; This package was written by Dave Gillespie; it is a complete -;; rewrite of Cesar Quiroz's original cl.el package of December 1986. -;; -;; This package works with Emacs 18, Emacs 19, and XEmacs/Lucid Emacs 19. -;; -;; Bug reports, comments, and suggestions are welcome! - -;; This file contains the portions of the Common Lisp extensions -;; package which should always be present. - - -;;; Future notes: - -;; Once Emacs 19 becomes standard, many things in this package which are -;; messy for reasons of compatibility can be greatly simplified. For now, -;; I prefer to maintain one unified version. - - -;;; Change Log: - -;; Version 2.02 (30 Jul 93): -;; * Added "cl-compat.el" file, extra compatibility with old package. -;; * Added `lexical-let' and `lexical-let*'. -;; * Added `define-modify-macro', `callf', and `callf2'. -;; * Added `ignore-errors'. -;; * Changed `(setf (nthcdr N PLACE) X)' to work when N is zero. -;; * Merged `*gentemp-counter*' into `*gensym-counter*'. -;; * Extended `subseq' to allow negative START and END like `substring'. -;; * Added `in-ref', `across-ref', `elements of-ref' loop clauses. -;; * Added `concat', `vconcat' loop clauses. -;; * Cleaned up a number of compiler warnings. - -;; Version 2.01 (7 Jul 93): -;; * Added support for FSF version of Emacs 19. -;; * Added `add-hook' for Emacs 18 users. -;; * Added `defsubst*' and `symbol-macrolet'. -;; * Added `maplist', `mapc', `mapl', `mapcan', `mapcon'. -;; * Added `map', `concatenate', `reduce', `merge'. -;; * Added `revappend', `nreconc', `tailp', `tree-equal'. -;; * Added `assert', `check-type', `typecase', `typep', and `deftype'. -;; * Added destructuring and `&environment' support to `defmacro*'. -;; * Added destructuring to `loop', and added the following clauses: -;; `elements', `frames', `overlays', `intervals', `buffers', `key-seqs'. -;; * Renamed `delete' to `delete*' and `remove' to `remove*'. -;; * Completed support for all keywords in `remove*', `substitute', etc. -;; * Added `most-positive-float' and company. -;; * Fixed hash tables to work with latest Lucid Emacs. -;; * `proclaim' forms are no longer compile-time-evaluating; use `declaim'. -;; * Syntax for `warn' declarations has changed. -;; * Improved implementation of `random*'. -;; * Moved most sequence functions to a new file, cl-seq.el. -;; * Moved `eval-when' into cl-macs.el. -;; * Moved `pushnew' and `adjoin' to cl.el for most common cases. -;; * Moved `provide' forms down to ends of files. -;; * Changed expansion of `pop' to something that compiles to better code. -;; * Changed so that no patch is required for Emacs 19 byte compiler. -;; * Made more things dependent on `optimize' declarations. -;; * Added a partial implementation of struct print functions. -;; * Miscellaneous minor changes. - -;; Version 2.00: -;; * First public release of this package. - - -;;; Code: - -(defvar cl-emacs-type (cond ((or (and (fboundp 'epoch::version) - (symbol-value 'epoch::version)) - (string-lessp emacs-version "19")) 18) - ((string-match "XEmacs" emacs-version) - 'lucid) - (t 19))) - -(or (fboundp 'defalias) (fset 'defalias 'fset)) - -(defvar cl-optimize-speed 1) -(defvar cl-optimize-safety 1) - - -;;; Keywords used in this package. - -;;; XEmacs - keywords are done in Fintern(). -;;; -;;; (defconst :test ':test) -;;; (defconst :test-not ':test-not) -;;; (defconst :key ':key) -;;; (defconst :start ':start) -;;; (defconst :start1 ':start1) -;;; (defconst :start2 ':start2) -;;; (defconst :end ':end) -;;; (defconst :end1 ':end1) -;;; (defconst :end2 ':end2) -;;; (defconst :count ':count) -;;; (defconst :initial-value ':initial-value) -;;; (defconst :size ':size) -;;; (defconst :from-end ':from-end) -;;; (defconst :rehash-size ':rehash-size) -;;; (defconst :rehash-threshold ':rehash-threshold) -;;; (defconst :allow-other-keys ':allow-other-keys) - - -(defvar custom-print-functions nil - "This is a list of functions that format user objects for printing. -Each function is called in turn with three arguments: the object, the -stream, and the print level (currently ignored). If it is able to -print the object it returns true; otherwise it returns nil and the -printer proceeds to the next function on the list. - -This variable is not used at present, but it is defined in hopes that -a future Emacs interpreter will be able to use it.") - - -;;; Predicates. - -(defun eql (a b) ; See compiler macro in cl-macs.el - "T if the two args are the same Lisp object. -Floating-point numbers of equal value are `eql', but they may not be `eq'." - (if (numberp a) - (equal a b) - (eq a b))) - - -;;; Generalized variables. These macros are defined here so that they -;;; can safely be used in .emacs files. - -(defmacro incf (place &optional x) - "(incf PLACE [X]): increment PLACE by X (1 by default). -PLACE may be a symbol, or any generalized variable allowed by `setf'. -The return value is the incremented value of PLACE." - (if (symbolp place) - (list 'setq place (if x (list '+ place x) (list '1+ place))) - (list 'callf '+ place (or x 1)))) - -(defmacro decf (place &optional x) - "(decf PLACE [X]): decrement PLACE by X (1 by default). -PLACE may be a symbol, or any generalized variable allowed by `setf'. -The return value is the decremented value of PLACE." - (if (symbolp place) - (list 'setq place (if x (list '- place x) (list '1- place))) - (list 'callf '- place (or x 1)))) - -(defmacro pop (place) - "(pop PLACE): remove and return the head of the list stored in PLACE. -Analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE))), though more -careful about evaluating each argument only once and in the right order. -PLACE may be a symbol, or any generalized variable allowed by `setf'." - (if (symbolp place) - (list 'car (list 'prog1 place (list 'setq place (list 'cdr place)))) - (cl-do-pop place))) - -(defmacro push (x place) - "(push X PLACE): insert X at the head of the list stored in PLACE. -Analogous to (setf PLACE (cons X PLACE)), though more careful about -evaluating each argument only once and in the right order. PLACE may -be a symbol, or any generalized variable allowed by `setf'." - (if (symbolp place) (list 'setq place (list 'cons x place)) - (list 'callf2 'cons x place))) - -(defmacro pushnew (x place &rest keys) - "(pushnew X PLACE): insert X at the head of the list if not already there. -Like (push X PLACE), except that the list is unmodified if X is `eql' to -an element already on the list. -Keywords supported: :test :test-not :key" - (if (symbolp place) (list 'setq place (list* 'adjoin x place keys)) - (list* 'callf2 'adjoin x place keys))) - -(defun cl-set-elt (seq n val) - (if (listp seq) (setcar (nthcdr n seq) val) (aset seq n val))) - -(defun cl-set-nthcdr (n list x) - (if (<= n 0) x (setcdr (nthcdr (1- n) list) x) list)) - -(defun cl-set-buffer-substring (start end val) - (save-excursion (delete-region start end) - (goto-char start) - (insert val) - val)) - -(defun cl-set-substring (str start end val) - (if end (if (< end 0) (incf end (length str))) - (setq end (length str))) - (if (< start 0) (incf start str)) - (concat (and (> start 0) (substring str 0 start)) - val - (and (< end (length str)) (substring str end)))) - - -;;; Control structures. - -;;; These macros are so simple and so often-used that it's better to have -;;; them all the time than to load them from cl-macs.el. - -(defmacro when (cond &rest body) - "(when COND BODY...): if COND yields non-nil, do BODY, else return nil." - (list 'if cond (cons 'progn body))) - -(defmacro unless (cond &rest body) - "(unless COND BODY...): if COND yields nil, do BODY, else return nil." - (cons 'if (cons cond (cons nil body)))) - -(defun cl-map-extents (&rest cl-args) - (if (fboundp 'next-overlay-at) (apply 'cl-map-overlays cl-args) - (if (fboundp 'map-extents) (apply 'map-extents cl-args)))) - - -;;; Blocks and exits. - -(defalias 'cl-block-wrapper 'identity) -(defalias 'cl-block-throw 'throw) - - -;;; Multiple values. True multiple values are not supported, or even -;;; simulated. Instead, multiple-value-bind and friends simply expect -;;; the target form to return the values as a list. - -(defalias 'values 'list) -(defalias 'values-list 'identity) -(defalias 'multiple-value-list 'identity) -(defalias 'multiple-value-call 'apply) ; only works for one arg -(defalias 'nth-value 'nth) - - -;;; Macros. - -(defvar cl-macro-environment nil) -;; XEmacs: we renamed the internal function to macroexpand-internal -;; to avoid doc-file problems. -(defvar cl-old-macroexpand (prog1 (symbol-function 'macroexpand-internal) - (defalias 'macroexpand 'cl-macroexpand))) - -(defun cl-macroexpand (cl-macro &optional cl-env) - "Return result of expanding macros at top level of FORM. -If FORM is not a macro call, it is returned unchanged. -Otherwise, the macro is expanded and the expansion is considered -in place of FORM. When a non-macro-call results, it is returned. - -The second optional arg ENVIRONMENT species an environment of macro -definitions to shadow the loaded ones for use in file byte-compilation." - (let ((cl-macro-environment cl-env)) - (while (progn (setq cl-macro (funcall cl-old-macroexpand cl-macro cl-env)) - (and (symbolp cl-macro) - (cdr (assq (symbol-name cl-macro) cl-env)))) - (setq cl-macro (cadr (assq (symbol-name cl-macro) cl-env)))) - cl-macro)) - - -;;; Declarations. - -(defvar cl-compiling-file nil) -(defun cl-compiling-file () - (or cl-compiling-file - ;; XEmacs change -; (and (boundp 'outbuffer) (bufferp (symbol-value 'outbuffer)) -; (equal (buffer-name (symbol-value 'outbuffer)) -; " *Compiler Output*")) - (and (boundp 'byte-compile-outbuffer) - (bufferp (symbol-value 'byte-compile-outbuffer)) - (equal (buffer-name (symbol-value 'byte-compile-outbuffer)) - " *Compiler Output*")) - )) - -(defvar cl-proclaims-deferred nil) - -(defun proclaim (spec) - (if (fboundp 'cl-do-proclaim) (cl-do-proclaim spec t) - (push spec cl-proclaims-deferred)) - nil) - -(defmacro declaim (&rest specs) - (let ((body (mapcar (function (lambda (x) (list 'proclaim (list 'quote x)))) - specs))) - (if (cl-compiling-file) (list* 'eval-when '(compile load eval) body) - (cons 'progn body)))) ; avoid loading cl-macs.el for eval-when - - -;;; Symbols. - -(defun cl-random-time () - (let* ((time (copy-sequence (current-time-string))) (i (length time)) (v 0)) - (while (>= (decf i) 0) (setq v (+ (* v 3) (aref time i)))) - v)) - -(defvar *gensym-counter* (* (logand (cl-random-time) 1023) 100)) - - -;;; Numbers. - -(defun floatp-safe (x) - "T if OBJECT is a floating point number. -On Emacs versions that lack floating-point support, this function -always returns nil." - (and (numberp x) (not (integerp x)))) - -(defun plusp (x) - "T if NUMBER is positive." - (> x 0)) - -(defun minusp (x) - "T if NUMBER is negative." - (< x 0)) - -(defun oddp (x) - "T if INTEGER is odd." - (eq (logand x 1) 1)) - -(defun evenp (x) - "T if INTEGER is even." - (eq (logand x 1) 0)) - -(defun cl-abs (x) - "Return the absolute value of ARG." - (if (>= x 0) x (- x))) -(or (fboundp 'abs) (defalias 'abs 'cl-abs)) ; This is built-in to Emacs 19 - -(defvar *random-state* (vector 'cl-random-state-tag -1 30 (cl-random-time))) - -;;; We use `eval' in case VALBITS differs from compile-time to load-time. -(defconst most-positive-fixnum (eval '(lsh -1 -1))) -(defconst most-negative-fixnum (eval '(- -1 (lsh -1 -1)))) - -;;; The following are actually set by cl-float-limits. -(defconst most-positive-float nil) -(defconst most-negative-float nil) -(defconst least-positive-float nil) -(defconst least-negative-float nil) -(defconst least-positive-normalized-float nil) -(defconst least-negative-normalized-float nil) -(defconst float-epsilon nil) -(defconst float-negative-epsilon nil) - - -;;; Sequence functions. - -(defalias 'copy-seq 'copy-sequence) - -(defun mapcar* (cl-func cl-x &rest cl-rest) - "Apply FUNCTION to each element of SEQ, and make a list of the results. -If there are several SEQs, FUNCTION is called with that many arguments, -and mapping stops as soon as the shortest list runs out. With just one -SEQ, this is like `mapcar'. With several, it is like the Common Lisp -`mapcar' function extended to arbitrary sequence types." - (if cl-rest - (if (or (cdr cl-rest) (nlistp cl-x) (nlistp (car cl-rest))) - (cl-mapcar-many cl-func (cons cl-x cl-rest)) - (let ((cl-res nil) (cl-y (car cl-rest))) - (while (and cl-x cl-y) - (push (funcall cl-func (pop cl-x) (pop cl-y)) cl-res)) - (nreverse cl-res))) - (mapcar cl-func cl-x))) - - -;;; List functions. - -(defalias 'first 'car) -(defalias 'rest 'cdr) -(defalias 'endp 'null) - -(defun second (x) - "Return the second element of the list LIST." - (car (cdr x))) - -(defun third (x) - "Return the third element of the list LIST." - (car (cdr (cdr x)))) - -(defun fourth (x) - "Return the fourth element of the list LIST." - (nth 3 x)) - -(defun fifth (x) - "Return the fifth element of the list LIST." - (nth 4 x)) - -(defun sixth (x) - "Return the sixth element of the list LIST." - (nth 5 x)) - -(defun seventh (x) - "Return the seventh element of the list LIST." - (nth 6 x)) - -(defun eighth (x) - "Return the eighth element of the list LIST." - (nth 7 x)) - -(defun ninth (x) - "Return the ninth element of the list LIST." - (nth 8 x)) - -(defun tenth (x) - "Return the tenth element of the list LIST." - (nth 9 x)) - -(defun caar (x) - "Return the `car' of the `car' of X." - (car (car x))) - -(defun cadr (x) - "Return the `car' of the `cdr' of X." - (car (cdr x))) - -(defun cdar (x) - "Return the `cdr' of the `car' of X." - (cdr (car x))) - -(defun cddr (x) - "Return the `cdr' of the `cdr' of X." - (cdr (cdr x))) - -(defun caaar (x) - "Return the `car' of the `car' of the `car' of X." - (car (car (car x)))) - -(defun caadr (x) - "Return the `car' of the `car' of the `cdr' of X." - (car (car (cdr x)))) - -(defun cadar (x) - "Return the `car' of the `cdr' of the `car' of X." - (car (cdr (car x)))) - -(defun caddr (x) - "Return the `car' of the `cdr' of the `cdr' of X." - (car (cdr (cdr x)))) - -(defun cdaar (x) - "Return the `cdr' of the `car' of the `car' of X." - (cdr (car (car x)))) - -(defun cdadr (x) - "Return the `cdr' of the `car' of the `cdr' of X." - (cdr (car (cdr x)))) - -(defun cddar (x) - "Return the `cdr' of the `cdr' of the `car' of X." - (cdr (cdr (car x)))) - -(defun cdddr (x) - "Return the `cdr' of the `cdr' of the `cdr' of X." - (cdr (cdr (cdr x)))) - -(defun caaaar (x) - "Return the `car' of the `car' of the `car' of the `car' of X." - (car (car (car (car x))))) - -(defun caaadr (x) - "Return the `car' of the `car' of the `car' of the `cdr' of X." - (car (car (car (cdr x))))) - -(defun caadar (x) - "Return the `car' of the `car' of the `cdr' of the `car' of X." - (car (car (cdr (car x))))) - -(defun caaddr (x) - "Return the `car' of the `car' of the `cdr' of the `cdr' of X." - (car (car (cdr (cdr x))))) - -(defun cadaar (x) - "Return the `car' of the `cdr' of the `car' of the `car' of X." - (car (cdr (car (car x))))) - -(defun cadadr (x) - "Return the `car' of the `cdr' of the `car' of the `cdr' of X." - (car (cdr (car (cdr x))))) - -(defun caddar (x) - "Return the `car' of the `cdr' of the `cdr' of the `car' of X." - (car (cdr (cdr (car x))))) - -(defun cadddr (x) - "Return the `car' of the `cdr' of the `cdr' of the `cdr' of X." - (car (cdr (cdr (cdr x))))) - -(defun cdaaar (x) - "Return the `cdr' of the `car' of the `car' of the `car' of X." - (cdr (car (car (car x))))) - -(defun cdaadr (x) - "Return the `cdr' of the `car' of the `car' of the `cdr' of X." - (cdr (car (car (cdr x))))) - -(defun cdadar (x) - "Return the `cdr' of the `car' of the `cdr' of the `car' of X." - (cdr (car (cdr (car x))))) - -(defun cdaddr (x) - "Return the `cdr' of the `car' of the `cdr' of the `cdr' of X." - (cdr (car (cdr (cdr x))))) - -(defun cddaar (x) - "Return the `cdr' of the `cdr' of the `car' of the `car' of X." - (cdr (cdr (car (car x))))) - -(defun cddadr (x) - "Return the `cdr' of the `cdr' of the `car' of the `cdr' of X." - (cdr (cdr (car (cdr x))))) - -(defun cdddar (x) - "Return the `cdr' of the `cdr' of the `cdr' of the `car' of X." - (cdr (cdr (cdr (car x))))) - -(defun cddddr (x) - "Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X." - (cdr (cdr (cdr (cdr x))))) - -(defun last (x &optional n) - "Returns the last link in the list LIST. -With optional argument N, returns Nth-to-last link (default 1)." - (if n - (let ((m 0) (p x)) - (while (consp p) (incf m) (pop p)) - (if (<= n 0) p - (if (< n m) (nthcdr (- m n) x) x))) - (while (consp (cdr x)) (pop x)) - x)) - -(defun butlast (x &optional n) - "Returns a copy of LIST with the last N elements removed." - (if (and n (<= n 0)) x - (nbutlast (copy-sequence x) n))) - -(defun nbutlast (x &optional n) - "Modifies LIST to remove the last N elements." - (let ((m (length x))) - (or n (setq n 1)) - (and (< n m) - (progn - (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil)) - x)))) - -(defun list* (arg &rest rest) ; See compiler macro in cl-macs.el - "Return a new list with specified args as elements, cons'd to last arg. -Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to -`(cons A (cons B (cons C D)))'." - (cond ((not rest) arg) - ((not (cdr rest)) (cons arg (car rest))) - (t (let* ((n (length rest)) - (copy (copy-sequence rest)) - (last (nthcdr (- n 2) copy))) - (setcdr last (car (cdr last))) - (cons arg copy))))) - -(defun ldiff (list sublist) - "Return a copy of LIST with the tail SUBLIST removed." - (let ((res nil)) - (while (and (consp list) (not (eq list sublist))) - (push (pop list) res)) - (nreverse res))) - -(defun copy-list (list) - "Return a copy of a list, which may be a dotted list. -The elements of the list are not copied, just the list structure itself." - (if (consp list) - (let ((res nil)) - (while (consp list) (push (pop list) res)) - (prog1 (nreverse res) (setcdr res list))) - (car list))) - -(defun cl-maclisp-member (item list) - (while (and list (not (equal item (car list)))) (setq list (cdr list))) - list) - -;;; Define an Emacs 19-compatible `member' for the benefit of Emacs 18 users. -(or (and (fboundp 'member) (subrp (symbol-function 'member))) - (defalias 'member 'cl-maclisp-member)) - -(defalias 'cl-member 'memq) ; for compatibility with old CL package -(defalias 'cl-floor 'floor*) -(defalias 'cl-ceiling 'ceiling*) -(defalias 'cl-truncate 'truncate*) -(defalias 'cl-round 'round*) -(defalias 'cl-mod 'mod*) - -(defun adjoin (cl-item cl-list &rest cl-keys) ; See compiler macro in cl-macs - "Return ITEM consed onto the front of LIST only if it's not already there. -Otherwise, return LIST unmodified. -Keywords supported: :test :test-not :key" - (cond ((or (equal cl-keys '(:test eq)) - (and (null cl-keys) (not (numberp cl-item)))) - (if (memq cl-item cl-list) cl-list (cons cl-item cl-list))) - ((or (equal cl-keys '(:test equal)) (null cl-keys)) - (if (member cl-item cl-list) cl-list (cons cl-item cl-list))) - (t (apply 'cl-adjoin cl-item cl-list cl-keys)))) - -(defun subst (cl-new cl-old cl-tree &rest cl-keys) - "Substitute NEW for OLD everywhere in TREE (non-destructively). -Return a copy of TREE with all elements `eql' to OLD replaced by NEW. -Keywords supported: :test :test-not :key" - (if (or cl-keys (and (numberp cl-old) (not (integerp cl-old)))) - (apply 'sublis (list (cons cl-old cl-new)) cl-tree cl-keys) - (cl-do-subst cl-new cl-old cl-tree))) - -(defun cl-do-subst (cl-new cl-old cl-tree) - (cond ((eq cl-tree cl-old) cl-new) - ((consp cl-tree) - (let ((a (cl-do-subst cl-new cl-old (car cl-tree))) - (d (cl-do-subst cl-new cl-old (cdr cl-tree)))) - (if (and (eq a (car cl-tree)) (eq d (cdr cl-tree))) - cl-tree (cons a d)))) - (t cl-tree))) - -(defun acons (a b c) (cons (cons a b) c)) -(defun pairlis (a b &optional c) (nconc (mapcar* 'cons a b) c)) - - -;;; Miscellaneous. - -;; XEmacs change -(define-error 'cl-assertion-failed "Assertion failed") - -;;; This is defined in Emacs 19; define it here for Emacs 18 users. -(defun cl-add-hook (hook func &optional append) - "Add to hook variable HOOK the function FUNC. -FUNC is not added if it already appears on the list stored in HOOK." - (let ((old (and (boundp hook) (symbol-value hook)))) - (and (listp old) (not (eq (car old) 'lambda)) - (setq old (list old))) - (and (not (member func old)) - (set hook (if append (nconc old (list func)) (cons func old)))))) -(or (fboundp 'add-hook) (defalias 'add-hook 'cl-add-hook)) - -;; XEmacs change -;(load "cl-defs") - -;;; Define data for indentation and edebug. -(mapcar (function - (lambda (entry) - (mapcar (function - (lambda (func) - (put func 'lisp-indent-function (nth 1 entry)) - (put func 'lisp-indent-hook (nth 1 entry)) - (or (get func 'edebug-form-spec) - (put func 'edebug-form-spec (nth 2 entry))))) - (car entry)))) - '(((defun* defmacro*) defun) - ((function*) nil - (&or symbolp ([&optional 'macro] 'lambda (&rest sexp) &rest form))) - ((eval-when) 1 (sexp &rest form)) - ((when unless) 1 (&rest form)) - ((declare) nil (&rest sexp)) - ((the) 1 (sexp &rest form)) - ((case ecase typecase etypecase) 1 (form &rest (sexp &rest form))) - ((block return-from) 1 (sexp &rest form)) - ((return) nil (&optional form)) - ((do do*) 2 ((&rest &or symbolp (symbolp &optional form form)) - (form &rest form) - &rest form)) - ((dolist dotimes) 1 ((symbolp form &rest form) &rest form)) - ((do-symbols) 1 ((symbolp form &optional form form) &rest form)) - ((do-all-symbols) 1 ((symbolp form &optional form) &rest form)) - ((psetq setf psetf) nil edebug-setq-form) - ((progv) 2 (&rest form)) - ((flet labels macrolet) 1 - ((&rest (sexp sexp &rest form)) &rest form)) - ((symbol-macrolet lexical-let lexical-let*) 1 - ((&rest &or symbolp (symbolp form)) &rest form)) - ((multiple-value-bind) 2 ((&rest symbolp) &rest form)) - ((multiple-value-setq) 1 ((&rest symbolp) &rest form)) - ((incf decf remf pop push pushnew shiftf rotatef) nil (&rest form)) - ((letf letf*) 1 ((&rest (&rest form)) &rest form)) - ((callf destructuring-bind) 2 (sexp form &rest form)) - ((callf2) 3 (sexp form form &rest form)) - ((loop) defun (&rest &or symbolp form)) - ((ignore-errors) 0 (&rest form)))) - - -;;; This goes here so that cl-macs can find it if it loads right now. -(provide 'cl-19) ; usage: (require 'cl-19 "cl") - - -;;; Things to do after byte-compiler is loaded. -;;; As a side effect, we cause cl-macs to be loaded when compiling, so -;;; that the compiler-macros defined there will be present. - -(defvar cl-hacked-flag nil) -(defun cl-hack-byte-compiler () - (if (and (not cl-hacked-flag) (fboundp 'byte-compile-file-form)) - (progn - (cl-compile-time-init) ; in cl-macs.el - (setq cl-hacked-flag t)))) - -;;; Try it now in case the compiler has already been loaded. -(cl-hack-byte-compiler) - -;;; Also make a hook in case compiler is loaded after this file. -;;; The compiler doesn't call any hooks when it loads or runs, but -;;; we can take advantage of the fact that emacs-lisp-mode will be -;;; called when the compiler reads in the file to be compiled. -;;; BUG: If the first compilation is `byte-compile' rather than -;;; `byte-compile-file', we lose. Oh, well. -(add-hook 'emacs-lisp-mode-hook 'cl-hack-byte-compiler) - - -;;; The following ensures that packages which expect the old-style cl.el -;;; will be happy with this one. - -(provide 'cl) - -(provide 'mini-cl) ; for Epoch - -(run-hooks 'cl-load-hook) - -;;; cl.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cmdloop.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cmdloop.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,549 @@ +;;; cmdloop.el --- support functions for the top-level command loop. + +;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc. + +;; Author: Richard Mlynarik +;; Date: 8-Jul-92 +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30. (Some of the stuff below is in FSF's subr.el.) + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +(defun recursion-depth () + "Return the current depth in recursive edits." + (+ command-loop-level (minibuffer-depth))) + +(defun top-level () + "Exit all recursive editing levels." + (interactive) + (throw 'top-level nil)) + +(defun exit-recursive-edit () + "Exit from the innermost recursive edit or minibuffer." + (interactive) + (if (> (recursion-depth) 0) + (throw 'exit nil)) + (error "No recursive edit is in progress")) + +(defun abort-recursive-edit () + "Abort the command that requested this recursive edit or minibuffer input." + (interactive) + (if (> (recursion-depth) 0) + (throw 'exit t)) + (error "No recursive edit is in progress")) + +;; (defun keyboard-quit () +;; "Signal a `quit' condition." +;; (interactive) +;; (deactivate-mark) +;; (signal 'quit nil)) + +;; moved here from pending-del. +(defun keyboard-quit () + "Signal a `quit' condition. +If this character is typed while lisp code is executing, it will be treated + as an interrupt. +If this character is typed at top-level, this simply beeps. +If `zmacs-regions' is true, and the zmacs region is active in this buffer, +then this key deactivates the region without beeping or signalling." + (interactive) + (if (and (region-active-p) + (eq (current-buffer) (zmacs-region-buffer))) + ;; pseudo-zmacs compatibility: don't beep if this ^G is simply + ;; deactivating the region. If it is inactive, beep. + nil + (signal 'quit nil))) + +(defvar buffer-quit-function nil + "Function to call to \"quit\" the current buffer, or nil if none. +\\[keyboard-escape-quit] calls this function when its more local actions +\(such as cancelling a prefix argument, minibuffer or region) do not apply.") + +(defun keyboard-escape-quit () + "Exit the current \"mode\" (in a generalized sense of the word). +This command can exit an interactive command such as `query-replace', +can clear out a prefix argument or a region, +can get out of the minibuffer or other recursive edit, +cancel the use of the current buffer (for special-purpose buffers), +or go back to just one window (by deleting all but the selected window)." + (interactive) + (cond ((eq last-command 'mode-exited) nil) + ((> (minibuffer-depth) 0) + (abort-recursive-edit)) + (current-prefix-arg + nil) + ((region-active-p) + (zmacs-deactivate-region)) + ((> (recursion-depth) 0) + (exit-recursive-edit)) + (buffer-quit-function + (funcall buffer-quit-function)) + ((not (one-window-p t)) + (delete-other-windows)) + ((string-match "^ \\*" (buffer-name (current-buffer))) + (bury-buffer)))) + +;;#### This should really be a ring of last errors. +(defvar last-error nil + "#### Document me.") + +;; #### Provisionally turned on for XEmacs 20.3beta. +(defcustom errors-deactivate-region nil + "*Non-nil means that errors will cause the region to be deactivated." + :type 'boolean + :group 'editing-basics) + +(defun command-error (error-object) + (let ((inhibit-quit t) + (debug-on-error nil) + (etype (car-safe error-object))) + (setq quit-flag nil) + (setq standard-output t) + (setq standard-input t) + (setq executing-kbd-macro nil) + (and errors-deactivate-region + (zmacs-deactivate-region)) + (discard-input) + + (setq last-error error-object) + + (message nil) + (ding nil (cond ((eq etype 'undefined-keystroke-sequence) + (if (and (vectorp (nth 1 error-object)) + (/= 0 (length (nth 1 error-object))) + (button-event-p (aref (nth 1 error-object) 0))) + 'undefined-click + 'undefined-key)) + ((eq etype 'quit) + 'quit) + ((memq etype '(end-of-buffer beginning-of-buffer)) + 'buffer-bound) + ((eq etype 'buffer-read-only) + 'read-only) + (t 'command-error))) + (display-error error-object t) + + (if (noninteractive) + (progn + (message "XEmacs exiting.") + (kill-emacs -1))) + t)) + +(defun describe-last-error () + "Redisplay the last error-message. See the variable `last-error'." + (interactive) + (with-displaying-help-buffer + (lambda () + (princ "Last error was:\n" standard-output) + (display-error last-error standard-output)))) + + +;;#### Must be done later in the loadup sequence +;(define-key (symbol-function 'help-command) "e" 'describe-last-error) + + +(defun truncate-command-history-for-gc () + (let ((tail (nthcdr 30 command-history))) + (if tail (setcdr tail nil))) + (let ((tail (nthcdr 30 values))) + (if tail (setcdr tail nil))) + ) + +(add-hook 'pre-gc-hook 'truncate-command-history-for-gc) + + +;;;; Object-oriented programming at its finest + +;; Now in src/print.c; used by Ferror_message_string and others +;(defun display-error (error-object stream) ;(defgeneric report-condition ...) +; "Display `error-object' on `stream' in a user-friendly way." +; (funcall (or (let ((type (car-safe error-object))) +; (catch 'error +; (and (consp error-object) +; (symbolp type) +; ;;(stringp (get type 'error-message)) +; (consp (get type 'error-conditions)) +; (let ((tail (cdr error-object))) +; (while (not (null tail)) +; (if (consp tail) +; (setq tail (cdr tail)) +; (throw 'error nil))) +; t) +; ;; (check-type condition condition) +; (get type 'error-conditions) +; ;; Search class hierarchy +; (let ((tail (get type 'error-conditions))) +; (while (not (null tail)) +; (cond ((not (and (consp tail) +; (symbolp (car tail)))) +; (throw 'error nil)) +; ((get (car tail) 'display-error) +; (throw 'error (get (car tail) +; 'display-error))) +; (t +; (setq tail (cdr tail))))) +; ;; Default method +; #'(lambda (error-object stream) +; (let ((type (car error-object)) +; (tail (cdr error-object)) +; (first t) +; (print-message-label 'error)) +; (if (eq type 'error) +; (progn (princ (car tail) stream) +; (setq tail (cdr tail))) +; (princ (or (gettext (get type 'error-message)) type) +; stream)) +; (while tail +; (princ (if first ": " ", ") stream) +; (prin1 (car tail) stream) +; (setq tail (cdr tail) +; first nil)))))))) +; #'(lambda (error-object stream) +; (princ (gettext "Peculiar error ") stream) +; (prin1 error-object stream))) +; error-object stream)) + +(put 'file-error 'display-error + #'(lambda (error-object stream) + (let ((tail (cdr error-object)) + (first t)) + (princ (car tail) stream) + (while (setq tail (cdr tail)) + (princ (if first ": " ", ") stream) + (princ (car tail) stream) + (setq first nil))))) + +(put 'undefined-keystroke-sequence 'display-error + #'(lambda (error-object stream) + (princ (key-description (car (cdr error-object))) stream) + ;; #### I18N3: doesn't localize properly. + (princ (gettext " not defined.") stream) ; doo dah, doo dah. + )) + + +(defcustom teach-extended-commands-p t + "*If true, then `\\[execute-extended-command]' will teach you keybindings. +Any time you execute a command with \\[execute-extended-command] which has a +shorter keybinding, you will be shown the alternate binding before the +command executes. There is a short pause after displaying the binding, +before executing it; the length can be controlled by +`teach-extended-commands-timeout'." + :type 'boolean + :group 'keyboard) + +(defcustom teach-extended-commands-timeout 4 + "*How long to pause after displaying a keybinding before executing. +The value is measured in seconds. This only applies if +`teach-extended-commands-p' is true." + :type 'number + :group 'keyboard) + +;That damn RMS went off and implemented something differently, after +;we had already implemented it. We can't support both properly until +;we have Lisp magic variables. +;(defvar suggest-key-bindings t +; "*FSFmacs equivalent of `teach-extended-commands-*'. +;Provided for compatibility only. +;Non-nil means show the equivalent key-binding when M-x command has one. +;The value can be a length of time to show the message for. +;If the value is non-nil and not a number, we wait 2 seconds.") +; +;(make-obsolete-variable 'suggest-key-bindings 'teach-extended-commands-p) + +(defun execute-extended-command (prefix-arg) + "Read a command name from the minibuffer using 'completing-read'. +Then call the specified command using 'command-execute' and return its +return value. If the command asks for a prefix argument, supply the +value of the current raw prefix argument, or the value of PREFIX-ARG +when called from Lisp." + (interactive "P") + ;; Note: This doesn't hack "this-command-keys" + (let ((prefix-arg prefix-arg)) + (setq this-command (read-command + ;; Note: this has the hard-wired + ;; "C-u" and "M-x" string bug in common + ;; with all GNU Emacs's. + ;; (i.e. it prints C-u and M-x regardless of + ;; whether some other keys were actually bound + ;; to `execute-extended-command' and + ;; `universal-argument'. + (cond ((eq prefix-arg '-) + "- M-x ") + ((equal prefix-arg '(4)) + "C-u M-x ") + ((integerp prefix-arg) + (format "%d M-x " prefix-arg)) + ((and (consp prefix-arg) + (integerp (car prefix-arg))) + (format "%d M-x " (car prefix-arg))) + (t + "M-x "))))) + + (if (and teach-extended-commands-p + (interactive-p)) + ;; We need to fiddle with keys: remember the keys, run the + ;; command, and show the keys (if any). + (let ((_execute_command_keys_ (where-is-internal this-command)) + (_execute_command_name_ this-command)) ; the name can change + (command-execute this-command t) + (when (and _execute_command_keys_ + ;; Wait for a while, so the user can see a message + ;; printed, if any. + (sit-for 1)) + (display-message + 'no-log + (format "Command `%s' is bound to key%s: %s" + _execute_command_name_ + (if (cdr _execute_command_keys_) "s" "") + (sorted-key-descriptions _execute_command_keys_))) + (sit-for teach-extended-commands-timeout) + (clear-message 'no-log))) + ;; Else, just run the command. + (command-execute this-command t))) + + +;;; C code calls this; the underscores in the variable names are to avoid +;;; cluttering the specbind namespace (lexical scope! lexical scope!) +;;; Putting this in Lisp instead of C slows kbd macros by 50%. +;(defun command-execute (_command &optional _record-flag) +; "Execute CMD as an editor command. +;CMD must be a symbol that satisfies the `commandp' predicate. +;Optional second arg RECORD-FLAG non-nil +;means unconditionally put this command in `command-history'. +;Otherwise, that is done only if an arg is read using the minibuffer." +; (let ((_prefix prefix-arg) +; (_cmd (indirect-function _command))) +; (setq prefix-arg nil +; this-command _command +; current-prefix-arg _prefix +; zmacs-region-stays nil) +; ;; #### debug_on_next_call = 0; +; (cond ((and (symbolp _command) +; (get _command 'disabled)) +; (run-hooks disabled-command-hook)) +; ((or (stringp _cmd) (vectorp _cmd)) +; ;; If requested, place the macro in the command history. +; ;; For other sorts of commands, call-interactively takes +; ;; care of this. +; (if _record-flag +; (setq command-history +; (cons (list 'execute-kbd-macro _cmd _prefix) +; command-history))) +; (execute-kbd-macro _cmd _prefix)) +; (t +; (call-interactively _command _record-flag))))) + +(defun y-or-n-p-minibuf (prompt) + "Ask user a \"y or n\" question. Return t if answer is \"y\". +Takes one argument, which is the string to display to ask the question. +It should end in a space; `y-or-n-p' adds `(y or n) ' to it. +No confirmation of the answer is requested; a single character is enough. +Also accepts Space to mean yes, or Delete to mean no." + (save-excursion + (let* ((pre "") + (yn (gettext "(y or n) ")) + ;; we need to translate the prompt ourselves because of the + ;; strange way we handle it. + (prompt (gettext prompt)) + event) + (while (stringp yn) + (if (let ((cursor-in-echo-area t) + (inhibit-quit t)) + (message "%s%s%s" pre prompt yn) + (setq event (next-command-event event)) + (condition-case nil + (prog1 + (or quit-flag (eq 'keyboard-quit (key-binding event))) + (setq quit-flag nil)) + (wrong-type-argument t))) + (progn + (message "%s%s%s%s" pre prompt yn (single-key-description event)) + (setq quit-flag nil) + (signal 'quit '()))) + (let* ((keys (events-to-keys (vector event))) + (def (lookup-key query-replace-map keys))) + (cond ((eq def 'skip) + (message "%s%sNo" prompt yn) + (setq yn nil)) + ((eq def 'act) + (message "%s%sYes" prompt yn) + (setq yn t)) + ((eq def 'recenter) + (recenter)) + ((or (eq def 'quit) (eq def 'exit-prefix)) + (signal 'quit '())) + ((button-release-event-p event) ; ignore them + nil) + (t + (message "%s%s%s%s" pre prompt yn + (single-key-description event)) + (ding nil 'y-or-n-p) + (discard-input) + (if (= (length pre) 0) + (setq pre (gettext "Please answer y or n. "))))))) + yn))) + +(defun yes-or-no-p-minibuf (prompt) + "Ask user a yes-or-no question. Return t if answer is yes. +Takes one argument, which is the string to display to ask the question. +It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it. +The user must confirm the answer with RET, +and can edit it until it has been confirmed." + (save-excursion + (let ((p (concat (gettext prompt) (gettext "(yes or no) "))) + (ans "")) + (while (stringp ans) + (setq ans (downcase (read-string p nil t))) ;no history + (cond ((string-equal ans (gettext "yes")) + (setq ans 't)) + ((string-equal ans (gettext "no")) + (setq ans 'nil)) + (t + (ding nil 'yes-or-no-p) + (discard-input) + (message "Please answer yes or no.") + (sleep-for 2)))) + ans))) + +;; these may be redefined later, but make the original def easily encapsulable +(define-function 'yes-or-no-p 'yes-or-no-p-minibuf) +(define-function 'y-or-n-p 'y-or-n-p-minibuf) + + +(defun read-char () + "Read a character from the command input (keyboard or macro). +If a mouse click or non-ASCII character is detected, an error is +signalled. The character typed is returned as an ASCII value. This +is most likely the wrong thing for you to be using: consider using +the `next-command-event' function instead." + (save-excursion + (let* ((inhibit-quit t) + (event (next-command-event))) + (prog1 (or (event-to-character event) + ;; Kludge. If the event we read was a mouse-release, + ;; discard it and read the next one. + (if (button-release-event-p event) + (event-to-character (next-command-event event))) + (error "Key read has no ASCII equivalent %S" event)) + ;; this is not necessary, but is marginally more efficient than GC. + (deallocate-event event))))) + +(defun read-char-exclusive () + "Read a character from the command input (keyboard or macro). +If a mouse click or non-ASCII character is detected, it is discarded. +The character typed is returned as an ASCII value. This is most likely +the wrong thing for you to be using: consider using the +`next-command-event' function instead." + (let ((inhibit-quit t) + event ch) + (while (progn + (setq event (next-command-event)) + (setq ch (event-to-character event)) + (deallocate-event event) + (null ch))) + ch)) + +(defun read-quoted-char (&optional prompt) + "Like `read-char', except that if the first character read is an octal +digit, we read up to two more octal digits and return the character +represented by the octal number consisting of those digits. +Optional argument PROMPT specifies a string to use to prompt the user." + (save-excursion + (let ((count 0) (code 0) + (prompt (and prompt (gettext prompt))) + char event) + (while (< count 3) + (let ((inhibit-quit (zerop count)) + ;; Don't let C-h get the help message--only help function keys. + (help-char nil) + (help-form + "Type the special character you want to use, +or three octal digits representing its character code.")) + (and prompt (display-message 'prompt (format "%s-" prompt))) + (setq event (next-command-event) + char (or (event-to-character event nil nil t) + (error "key read cannot be inserted in a buffer: %S" + event))) + (if inhibit-quit (setq quit-flag nil))) + (cond ((null char)) + ((and (<= ?0 char) (<= char ?7)) + (setq code (+ (* code 8) (- char ?0)) + count (1+ count)) + (and prompt (display-message + 'prompt + (setq prompt (format "%s %c" prompt char))))) + ((> count 0) + (setq unread-command-event event + count 259)) + (t (setq code char count 259)))) + ;; Turn a meta-character into a character with the 0200 bit set. + (logior (if (/= (logand code ?\M-\^@) 0) 128 0) + (logand 255 code))))) + +(defun momentary-string-display (string pos &optional exit-char message) + "Momentarily display STRING in the buffer at POS. +Display remains until next character is typed. +If the char is EXIT-CHAR (optional third arg, default is SPC) it is swallowed; +otherwise it is then available as input (as a command if nothing else). +Display MESSAGE (optional fourth arg) in the echo area. +If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there." + (or exit-char (setq exit-char ?\ )) + (let ((buffer-read-only nil) + ;; Don't modify the undo list at all. + (buffer-undo-list t) + (modified (buffer-modified-p)) + (name buffer-file-name) + insert-end) + (unwind-protect + (progn + (save-excursion + (goto-char pos) + ;; defeat file locking... don't try this at home, kids! + (setq buffer-file-name nil) + (insert-before-markers (gettext string)) + (setq insert-end (point)) + ;; If the message end is off frame, recenter now. + (if (> (window-end) insert-end) + (recenter (/ (window-height) 2))) + ;; If that pushed message start off the frame, + ;; scroll to start it at the top of the frame. + (move-to-window-line 0) + (if (> (point) pos) + (progn + (goto-char pos) + (recenter 0)))) + (message (or message (gettext "Type %s to continue editing.")) + (single-key-description exit-char)) + (let ((event (save-excursion (next-command-event)))) + (or (eq (event-to-character event) exit-char) + (setq unread-command-event event)))) + (if insert-end + (save-excursion + (delete-region pos insert-end))) + (setq buffer-file-name name) + (set-buffer-modified-p modified)))) + +;;; cmdloop.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/auto-autoloads.el --- a/lisp/comint/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'comint-autoloads) (error "Already loaded")) - -;;;### (autoloads (background) "background" "comint/background.el") - -(autoload 'background "background" "\ -Run COMMAND in the background like csh. -A message is displayed when the job starts and finishes. The buffer is in -comint mode, so you can send input and signals to the job. The process object -is returned if anyone cares. See also comint-mode and the variables -background-show and background-select. - -Optional second argument BUFFER-NAME is a buffer to insert the output into. -If omitted, a buffer name is constructed from the command run." t nil) - -;;;*** - -;;;### (autoloads (comint-dynamic-list-completions comint-dynamic-complete comint-run make-comint) "comint" "comint/comint.el") - -(autoload 'make-comint "comint" "\ -Make a comint process NAME in a buffer, running PROGRAM. -The name of the buffer is made by surrounding NAME with `*'s. -PROGRAM should be either a string denoting an executable program to create -via `start-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP -connection to be opened via `open-network-stream'. If there is already a -running process in that buffer, it is not restarted. Optional third arg -STARTFILE is the name of a file to send the contents of to the process. - -If PROGRAM is a string, any more args are arguments to PROGRAM." nil nil) - -(autoload 'comint-run "comint" "\ -Run PROGRAM in a comint buffer and switch to it. -The buffer name is made by surrounding the file name of PROGRAM with `*'s. -The file name is used to make a symbol name, such as `comint-sh-hook', and any -hooks on this symbol are run in the buffer. -See `make-comint' and `comint-exec'." t nil) - -(autoload 'comint-dynamic-complete "comint" "\ -Dynamically perform completion at point. -Calls the functions in `comint-dynamic-complete-functions' to perform -completion until a function returns non-nil, at which point completion is -assumed to have occurred." t nil) - -(autoload 'comint-dynamic-list-completions "comint" "\ -List in help buffer sorted COMPLETIONS. -Typing SPC flushes the help buffer." nil nil) - -;;;*** - -;;;### (autoloads (gdb-with-core gdb) "gdb" "comint/gdb.el") - -(defvar gdb-command-name "gdb" "\ -Pathname for executing gdb.") - -(autoload 'gdb "gdb" "\ -Run gdb on program FILE in buffer *gdb-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for GDB. If you wish to change this, use -the GDB commands `cd DIR' and `directory'." t nil) - -(autoload 'gdb-with-core "gdb" "\ -Debug a program using a corefile." t nil) - -;;;*** - -;;;### (autoloads (gdbsrc) "gdbsrc" "comint/gdbsrc.el") - -(autoload 'gdbsrc "gdbsrc" "\ -Activates a gdb session with gdbsrc-mode turned on. A numeric prefix -argument can be used to specify a running process to attach, and a non-numeric -prefix argument will cause you to be prompted for a core file to debug." t nil) - -;;;*** - -;;;### (autoloads (perldb xdb dbx sdb) "gud" "comint/gud.el") - -(autoload 'sdb "gud" "\ -Run sdb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -(autoload 'dbx "gud" "\ -Run dbx on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -(autoload 'xdb "gud" "\ -Run xdb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger. - -You can set the variable 'gud-xdb-directories' to a list of program source -directories if your program contains sources from more than one directory." t nil) - -(autoload 'perldb "gud" "\ -Run perldb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -;;;*** - -;;;### (autoloads nil "inf-lisp" "comint/inf-lisp.el") - -(add-hook 'same-window-buffer-names "*inferior-lisp*") - -;;;*** - -;;;### (autoloads (rlogin) "rlogin" "comint/rlogin.el") - -(add-hook 'same-window-regexps "^\\*rlogin-.*\\*\\(\\|<[0-9]+>\\)") - -(autoload 'rlogin "rlogin" "\ -Open a network login connection to HOST via the `rlogin' program. -Input is sent line-at-a-time to the remote connection. - -Communication with the remote host is recorded in a buffer `*rlogin-HOST*' -\(or `*rlogin-USER@HOST*' if the remote username differs). -If a prefix argument is given and the buffer `*rlogin-HOST*' already exists, -a new buffer with a different connection will be made. - -When called from a program, if the optional second argument is a string or -buffer, it names the buffer to use. - -The variable `rlogin-program' contains the name of the actual program to -run. It can be a relative or absolute path. - -The variable `rlogin-explicit-args' is a list of arguments to give to -the rlogin when starting. They are added after any arguments given in -INPUT-ARGS. - -If the default value of `rlogin-directory-tracking-mode' is t, then the -default directory in that buffer is set to a remote (FTP) file name to -access your home directory on the remote machine. Occasionally this causes -an error, if you cannot access the home directory on that machine. This -error is harmless as long as you don't try to use that default directory. - -If `rlogin-directory-tracking-mode' is neither t nor nil, then the default -directory is initially set up to your (local) home directory. -This is useful if the remote machine and your local machine -share the same files via NFS. This is the default. - -If you wish to change directory tracking styles during a session, use the -function `rlogin-directory-tracking-mode' rather than simply setting the -variable." t nil) - -;;;*** - -;;;### (autoloads (shell) "shell" "comint/shell.el") - -(defvar shell-prompt-pattern (purecopy "^[^#$%>\n]*[#$%>] *") "\ -Regexp to match prompts in the inferior shell. -Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well. -This variable is used to initialise `comint-prompt-regexp' in the -shell buffer. - -The pattern should probably not match more than one line. If it does, -shell-mode may become confused trying to distinguish prompt from input -on lines which don't start with a prompt. - -This is a fine thing to set in your `.emacs' file.") - -(autoload 'shell "shell" "\ -Run an inferior shell, with I/O through buffer *shell*. -If buffer exists but shell process is not running, make new shell. -If buffer exists and shell process is running, - just switch to buffer `*shell*'. -Program used comes from variable `explicit-shell-file-name', - or (if that is nil) from the ESHELL environment variable, - or else from SHELL if there is no ESHELL. -If a file `~/.emacs_SHELLNAME' exists, it is given as initial input - (Note that this may lose due to a timing error if the shell - discards input when it starts up.) -The buffer is put in Shell mode, giving commands for sending input -and controlling the subjobs of the shell. See `shell-mode'. -See also the variable `shell-prompt-pattern'. - -The shell file name (sans directories) is used to make a symbol name -such as `explicit-csh-args'. If that symbol is a variable, -its value is used as a list of arguments when invoking the shell. -Otherwise, one argument `-i' is passed to the shell. - -\(Type \\[describe-mode] in the shell buffer for a list of commands.)" t nil) - -(add-hook 'same-window-buffer-names "*shell*") - -;;;*** - -;;;### (autoloads (ssh) "ssh" "comint/ssh.el") - -(add-hook 'same-window-regexps "^\\*ssh-.*\\*\\(\\|<[0-9]+>\\)") - -(autoload 'ssh "ssh" "\ -Open a network login connection via `ssh' with args INPUT-ARGS. -INPUT-ARGS should start with a host name; it may also contain -other arguments for `ssh'. - -Input is sent line-at-a-time to the remote connection. - -Communication with the remote host is recorded in a buffer `*ssh-HOST*' -\(or `*ssh-USER@HOST*' if the remote username differs). -If a prefix argument is given and the buffer `*ssh-HOST*' already exists, -a new buffer with a different connection will be made. - -When called from a program, if the optional second argument BUFFER is -a string or buffer, it specifies the buffer to use. - -The variable `ssh-program' contains the name of the actual program to -run. It can be a relative or absolute path. - -The variable `ssh-explicit-args' is a list of arguments to give to -the ssh when starting. They are prepended to any arguments given in -INPUT-ARGS. - -If the default value of `ssh-directory-tracking-mode' is t, then the -default directory in that buffer is set to a remote (FTP) file name to -access your home directory on the remote machine. Occasionally this causes -an error, if you cannot access the home directory on that machine. This -error is harmless as long as you don't try to use that default directory. - -If `ssh-directory-tracking-mode' is neither t nor nil, then the default -directory is initially set up to your (local) home directory. -This is useful if the remote machine and your local machine -share the same files via NFS. This is the default. - -If you wish to change directory tracking styles during a session, use the -function `ssh-directory-tracking-mode' rather than simply setting the -variable." t nil) - -;;;*** - -;;;### (autoloads (rsh telnet) "telnet" "comint/telnet.el") - -(add-hook 'same-window-regexps "\\*telnet-.*\\*\\(\\|<[0-9]+>\\)") - -(autoload 'telnet "telnet" "\ -Open a network login connection to host named HOST (a string). -With a prefix argument, prompts for the port name or number as well. -Communication with HOST is recorded in a buffer `*HOST-telnet*'. -Normally input is edited in Emacs and sent a line at a time. -See also `\\[rsh]'." t nil) - -(add-hook 'same-window-regexps "\\*rsh-[^-]*\\*\\(\\|<[0-9]*>\\)") - -(autoload 'rsh "telnet" "\ -Open a network login connection to host named HOST (a string). -Communication with HOST is recorded in a buffer `*rsh-HOST*'. -Normally input is edited in Emacs and sent a line at a time. -See also `\\[telnet]'." t nil) - -;;;*** - -(provide 'comint-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/background.el --- a/lisp/comint/background.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,137 +0,0 @@ -;;; background.el --- fun with background jobs - -;; Copyright (C) 1988 Joe Keane -;; Keywords: processes - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2 of the License, or -;; (at your option) any later version. - -;; XEmacs 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 XEmacs; if not, write to the Free Software -;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; - Adapted to use comint and cleaned up somewhat. Olin Shivers 5/90 -;; - Background failed to set the process buffer's working directory -;; in some cases. Fixed. Olin 6/14/90 -;; - Background failed to strip leading cd's off the command string -;; after performing them. This screwed up relative pathnames. -;; Furthermore, the proc buffer's default dir wasn't initialised -;; to the user's buffer's default dir before doing the leading cd. -;; This also screwed up relative pathnames if the proc buffer already -;; existed and was set to a different default dir. Hopefully we've -;; finally got it right. The pwd is now reported in the buffer -;; just to let the user know. Bug reported by Piet Van Oostrum. -;; Olin 10/19/90 -;; - Fixed up the sentinel to protect match-data around invocations. -;; Also slightly rearranged the cd match code for similar reasons. -;; Olin 7/16/91 -;; - Dec 29 1995: changed for new stuff (shell-command-switch, second -;; arg to shell-command --> BUFFER-NAME arg to background) from -;; FSF 19.30. Ben Wing - -;;; Code: - -(provide 'background) -(require 'comint) - -(defgroup background nil - "Fun with background jobs" - :group 'processes) - - -;; user variables -(defcustom background-show t - "*If non-nil, background jobs' buffers are shown when they're started." - :type 'boolean - :group 'background) -(defcustom background-select nil - "*If non-nil, background jobs' buffers are selected when they're started." - :type 'boolean - :group 'background) - -;;;###autoload -(defun background (command &optional buffer-name) - "Run COMMAND in the background like csh. -A message is displayed when the job starts and finishes. The buffer is in -comint mode, so you can send input and signals to the job. The process object -is returned if anyone cares. See also comint-mode and the variables -background-show and background-select. - -Optional second argument BUFFER-NAME is a buffer to insert the output into. -If omitted, a buffer name is constructed from the command run." - (interactive "s%% ") - (let ((job-number 1) - job-name - (dir default-directory)) - (while (get-process (setq job-name (format "background-%d" job-number))) - (setq job-number (1+ job-number))) - (or buffer-name - (setq buffer-name (format "*%s*" job-name))) - (if background-select (pop-to-buffer buffer-name) - (if background-show (with-output-to-temp-buffer buffer-name)) ; cute - (set-buffer (get-buffer-create buffer-name))) - (erase-buffer) - - (setq default-directory dir) ; Do this first, in case cd is relative path. - (if (string-match "^cd[\t ]+\\([^\t ;]+\\)[\t ]*;[\t ]*" command) - (let ((dir (substring command (match-beginning 1) (match-end 1)))) - (setq command (substring command (match-end 0))) - (setq default-directory - (file-name-as-directory (expand-file-name dir))))) - - (insert "--- working directory: " default-directory - "\n% " command ?\n) - - (let ((proc (get-buffer-process - (comint-exec buffer-name job-name shell-file-name - nil (list shell-command-switch command))))) - (comint-mode) - ;; COND because the proc may have died before the G-B-P is called. - (cond (proc (set-process-sentinel proc 'background-sentinel) - (message "[%d] %d" job-number (process-id proc)))) - (setq mode-name "Background") - proc))) - - -(defun background-sentinel (process msg) - "Called when a background job changes state." - (let ((ms (match-data))) ; barf - (unwind-protect - (let ((msg (cond ((string= msg "finished\n") "Done") - ((string-match "^exited" msg) - (concat "Exit " (substring msg 28 -1))) - ((zerop (length msg)) "Continuing") - (t (concat (upcase (substring msg 0 1)) - (substring msg 1 -1)))))) - (message "[%s] %s %s" (process-name process) - msg - (nth 2 (process-command process))) - (if (null (buffer-name (process-buffer process))) - (set-process-buffer process nil) ; WHY? Olin. - (if (memq (process-status process) '(signal exit)) - (save-excursion - (set-buffer (process-buffer process)) - (let ((at-end (eobp))) - (save-excursion - (goto-char (point-max)) - (insert ?\n msg ? - (substring (current-time-string) 11 19) ?\n)) - (if at-end (goto-char (point-max)))) - (set-buffer-modified-p nil))))) - (store-match-data ms)))) - -;;; background.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/comint-xemacs.el --- a/lisp/comint/comint-xemacs.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -;;; comint-xemacs.el --- Face customizations for comint - -;; Copyright (C) 1997 by Free Software Foundation, Inc. - -;; Author: Steven L Baur -;; Keywords: help, faces - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; Declare customizable faces for comint outside the main code so it can -;; be dumped with XEmacs. - -;;; Code: - -(defgroup comint nil - "General command interpreter in a window stuff." - :group 'processes) - -(defface comint-input-face '((((class color) - (background dark)) - (:foreground "red")) - (((class color) - (background light)) - (:foreground "blue")) - (t - (:bold t))) - "How to display user input for comint shells." - :group 'comint) - - - -(provide 'comint-xemacs) - -;;; comint-xemacs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/comint.el --- a/lisp/comint/comint.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2855 +0,0 @@ -;;; comint.el --- general command interpreter in a window stuff - -;; Copyright (C) 1988, 90, 92, 93, 94, 95 Free Software Foundation, Inc. - -;; Author: Olin Shivers -;; Adapted-by: Simon Marshall -;; Keywords: processes - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;;; Please send me bug reports, bug fixes, and extensions, so that I can -;;; merge them into the master source. -;;; - Olin Shivers (shivers@cs.cmu.edu) -;;; - Simon Marshall (simon@gnu.ai.mit.edu) - -;;; This file defines a general command-interpreter-in-a-buffer package -;;; (comint mode). The idea is that you can build specific process-in-a-buffer -;;; modes on top of comint mode -- e.g., lisp, shell, scheme, T, soar, .... -;;; This way, all these specific packages share a common base functionality, -;;; and a common set of bindings, which makes them easier to use (and -;;; saves code, implementation time, etc., etc.). - -;;; Several packages are already defined using comint mode: -;;; - shell.el defines a shell-in-a-buffer mode. -;;; - cmulisp.el defines a simple lisp-in-a-buffer mode. -;;; -;;; - The file cmuscheme.el defines a scheme-in-a-buffer mode. -;;; - The file tea.el tunes scheme and inferior-scheme modes for T. -;;; - The file soar.el tunes lisp and inferior-lisp modes for Soar. -;;; - cmutex.el defines tex and latex modes that invoke tex, latex, bibtex, -;;; previewers, and printers from within emacs. -;;; - background.el allows csh-like job control inside emacs. -;;; It is pretty easy to make new derived modes for other processes. - -;;; For documentation on the functionality provided by comint mode, and -;;; the hooks available for customising it, see the comments below. -;;; For further information on the standard derived modes (shell, -;;; inferior-lisp, inferior-scheme, ...), see the relevant source files. - -;;; For hints on converting existing process modes (e.g., tex-mode, -;;; background, dbx, gdb, kermit, prolog, telnet) to use comint-mode -;;; instead of shell-mode, see the notes at the end of this file. - - -;;; Brief Command Documentation: -;;;============================================================================ -;;; Comint Mode Commands: (common to all derived modes, like shell & cmulisp -;;; mode) -;;; -;;; XEmacs - FSF19 binds M-p/M-n to comint-{previous,next}-input instead of -;;; comint-{previous,next}-matching-input-from-input. -;;; XEmacs is mo' better. -;;; -;;; -;;; m-p comint-previous-matching-input-from-input Cycle backwards in input history -;;; m-n comint-next-matching-input-from-input Cycle forwards -;;; m-r comint-previous-matching-input Previous input matching a regexp -;;; m-s comint-next-matching-input Next input that matches -;;; XEmacs - remove evil binding of M-C-l. It's already bound to C-c C-r. -;;; NOT: m-c-l comint-show-output Show last batch of process output -;;; m-c-r comint-previous-input-matching Search backwards in input history -;;; return comint-send-input -;;; XEmacs - fsf nuked the binding for ^A, and we nuked the binding for ^D -;;; c-a comint-bol Beginning of line; skip prompt -;;; NOT: c-d comint-delchar-or-maybe-eof Delete char unless at end of buff -;;; c-c c-a comint-bol Beginning of line; skip prompt -;;; c-c c-d comint-send-eof ^d -;;; c-c c-u comint-kill-input ^u -;;; c-c c-w backward-kill-word ^w -;;; c-c c-c comint-interrupt-subjob ^c -;;; c-c c-z comint-stop-subjob ^z -;;; c-c c-\ comint-quit-subjob ^\ -;;; c-c c-o comint-kill-output Delete last batch of process output -;;; c-c c-r comint-show-output Show last batch of process output -;;; c-c c-l comint-dynamic-list-input-ring List input history -;;; -;;; 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-dynamic-complete-filename Complete filename at point. -;;; comint-dynamic-complete-variable Complete variable name at point. -;;; comint-dynamic-list-filename-completions List completions in help buffer. -;;; comint-replace-by-expanded-filename Expand and complete filename at point; -;;; replace with expanded/completed name. -;;; comint-replace-by-expanded-history Expand history at point; -;;; replace with expanded name. -;;; comint-magic-space Expand history and add (a) space(s). -;;; comint-kill-subjob No mercy. -;;; comint-show-maximum-output Show as much output as possible. -;;; comint-continue-subjob Send CONT signal to buffer's process -;;; group. Useful if you accidentally -;;; suspend your process (with C-c C-z). - -;;; comint-mode-hook is the comint mode hook. Basically for your keybindings. - -;;; Code: - -(require 'ring) - -;;; Buffer Local Variables: -;;;============================================================================ -;;; Comint mode buffer local variables: -;;; comint-prompt-regexp - string comint-bol uses to match prompt -;;; comint-delimiter-argument-list - list For delimiters and arguments -;;; comint-last-input-start - marker Handy if inferior always echoes -;;; comint-last-input-end - marker For comint-kill-output command -;;; comint-input-ring-size - integer For the input history -;;; comint-input-ring - ring mechanism -;;; comint-input-ring-index - number ... -;;; comint-input-autoexpand - symbol ... -;;; comint-input-ignoredups - boolean ... -;;; comint-last-input-match - string ... -;;; comint-dynamic-complete-functions - hook For the completion mechanism -;;; comint-completion-fignore - list ... -;;; comint-file-name-quote-list - list ... -;;; comint-get-old-input - function Hooks for specific -;;; comint-input-filter-functions - hook process-in-a-buffer -;;; comint-output-filter-functions - hook function modes. -;;; comint-input-filter - function ... -;;; comint-input-sender - function ... -;;; comint-eol-on-send - boolean ... -;;; comint-process-echoes - boolean ... -;;; comint-scroll-to-bottom-on-input - symbol For scroll behavior -;;; comint-scroll-to-bottom-on-output - symbol ... -;;; comint-scroll-show-maximum-output - boolean... -;;; -;;; Comint mode non-buffer local variables: -;;; comint-completion-addsuffix - boolean/cons For file name completion -;;; comint-completion-autolist - boolean behavior -;;; comint-completion-recexact - boolean ... - -(require 'easymenu) - -(defgroup comint nil - "General command interpreter in a window stuff." - :group 'processes) - -(defgroup comint-completion nil - "Completion facilities in comint" - :group 'comint) - -(defgroup comint-source nil - "Source finding facilities in comint" - :prefix "comint-" - :group 'comint) - - -(defvar comint-prompt-regexp "^" - "Regexp to recognise prompts in the inferior process. -Defaults to \"^\", the null string at BOL. - -Good choices: - Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp) - Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\" - franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\" - kcl: \"^>+ *\" - shell: \"^[^#$%>\\n]*[#$%>] *\" - T: \"^>+ *\" - -The pattern should begin with \"^\". It can match text on more than one line. -This pattern gets handed to re-search-backward, not looking-at. - -This is a good thing to set in mode hooks.") - -(defvar comint-delimiter-argument-list () - "List of characters to recognise as separate arguments in input. -Strings comprising a character in this list will separate the arguments -surrounding them, and also be regarded as arguments in their own right (unlike -whitespace). See `comint-arguments'. -Defaults to the empty list. - -For shells, a good value is (?\\| ?& ?< ?> ?\\( ?\\) ?;). - -This is a good thing to set in mode hooks.") - -;; #### BUG: this loser mangles history; when one types -;; find /tmp \( -name foo \) -print -;; one gets find /tmp \ ( -name foo \ ) -print -;; -;; XEmacs - So turn this off by default. -- jwz -;; -(defcustom comint-input-autoexpand nil - "*If non-nil, expand input command history references on completion. -This mirrors the optional behavior of tcsh (its autoexpand and histlit). - -If the value is `input', then the expansion is seen on input. -If the value is `history', then the expansion is only when inserting -into the buffer's input ring. See also `comint-magic-space' and -`comint-dynamic-complete'. - -This variable is buffer-local." - :type '(choice (const :tag "off" nil) - (const :tag "on" t) - (const input) - (const history)) - :group 'comint) - -;; XEmacs - this should default to t for consistency with minibuffer history. -jwz -(defcustom comint-input-ignoredups t - "*If non-nil, don't add input matching the last on the input ring. -This mirrors the optional behavior of bash. - -This variable is buffer-local." - :type 'boolean - :group 'comint) - -(defcustom comint-input-ring-file-name nil - "*If non-nil, name of the file to read/write input history. -See also `comint-read-input-ring' and `comint-write-input-ring'. - -This variable is buffer-local, and is a good thing to set in mode hooks." - :type '(choice (const :tag "None" nil) - (file)) - :group 'comint) - -(defcustom comint-scroll-to-bottom-on-input nil - "*Controls whether input to interpreter causes window to scroll. -If nil, then do not scroll. If t or `all', scroll all windows showing buffer. -If `this', scroll only the selected window. - -The default is nil. - -See `comint-preinput-scroll-to-bottom'. This variable is buffer-local." - :type '(choice (const :tag "off" nil) - (const t) - (const all) - (const this)) - :group 'comint) - -(defcustom comint-scroll-to-bottom-on-output nil - "*Controls whether interpreter output causes window to scroll. -If nil, then do not scroll. If t or `all', scroll all windows showing buffer. -If `this', scroll only the selected window. -If `others', scroll only those that are not the selected window. - -The default is nil. - -See variable `comint-scroll-show-maximum-output' and function -`comint-postoutput-scroll-to-bottom'. This variable is buffer-local." - :type '(choice (const :tag "off" nil) - (const t) - (const all) - (const this) - (const others)) - :group 'comint) - -(defcustom comint-scroll-show-maximum-output t - "*Controls how interpreter output causes window to scroll. -If non-nil, then show the maximum output when the window is scrolled. - -You may set this to an integer number of lines to keep shown, or a -floating point percentage of the window size to keep filled. -A negative number expresses a distance from the bottom, as when using -a prefix argument with `recenter' (bound to `\\[recenter]'). - -See variable `comint-scroll-to-bottom-on-output' and function -`comint-postoutput-scroll-to-bottom'. This variable is buffer-local." - :type '(choice (const :tag "Off" nil) - (const :tag "On" t) - (integer :tag "Number of lines" 20) - (number :tag "Decimal Percent of window" .85)) - :group 'comint) - -(defcustom comint-buffer-maximum-size 1024 - "*The maximum size in lines for comint buffers. -Comint buffers are truncated from the top to be no greater than this number, if -the function `comint-truncate-buffer' is on `comint-output-filter-functions'." - :type 'integer - :group 'comint) - -(defvar comint-input-ring-size 32 - "Size of input history ring.") - -(defcustom comint-process-echoes nil - "*If non-nil, assume that the subprocess echoes any input. -If so, delete one copy of the input so that only one copy eventually -appears in the buffer. - -This variable is buffer-local." - :type 'boolean - :group 'comint) - -;; AIX puts the name of the person being su'd to in from of the prompt. -(defcustom comint-password-prompt-regexp - (if (eq system-type 'aix-v3) - "\\(\\([Oo]ld \\|[Nn]ew \\|^\\|^..*s\\)[Pp]assword\\|pass phrase\\):\\s *\\'" - "\\(\\([Oo]ld \\|[Nn]ew \\|^\\)[Pp]assword\\|pass phrase\\):\\s *\\'") - "*Regexp matching prompts for passwords in the inferior process. -This is used by `comint-watch-for-password-prompt'." - :type 'regexp - :group 'comint) - -;;; Here are the per-interpreter hooks. -(defvar comint-get-old-input (function comint-get-old-input-default) - "Function that returns old text in comint mode. -This function is called when return is typed while the point is in old text. -It returns the text to be submitted as process input. The default is -`comint-get-old-input-default', which grabs the current line, and strips off -leading text matching `comint-prompt-regexp'.") - -;; XEmacs - fsf doesn't have this, and I think it ought to default to 't' -;; because it's good idiot-proof interface. --stig -(defcustom comint-append-old-input t - "*If nil, old text selected by \\[comint-send-input] is re-sent immediately. -If non-nil, the old text is appended to the end of the buffer, -and a prompting message is printed. - -This flag does not affect the behavior of \\[comint-send-input] -after the process output mark." - :type 'boolean - :group 'comint) - -(defvar comint-dynamic-complete-functions - '(comint-replace-by-expanded-history comint-dynamic-complete-filename) - "List of functions called to perform completion. -Functions should return non-nil if completion was performed. -See also `comint-dynamic-complete'. - -This is a good thing to set in mode hooks.") - -(defvar comint-input-filter - #'(lambda (str) - (and (not (string-match "\\`\\s *\\'" str)) - ;; XEmacs - ignore '!!' and kin - (> (length str) 2))) - "Predicate for filtering additions to input history. -Takes one argument, the input. If non-nil, the input may be saved on the input -history list. Default is to save anything longer than two characters -that isn't all whitespace.") - -(defvar comint-input-filter-functions '() - "Functions to call before input is sent to the process. -These functions get one argument, a string containing the text to send. - -This variable is buffer-local.") - -(defvar comint-output-filter-functions '(comint-postoutput-scroll-to-bottom - ;; XEmacs - not here by default for FSF - comint-watch-for-password-prompt) - "Functions to call after output is inserted into the buffer. -One possible function is `comint-postoutput-scroll-to-bottom'. -These functions get one argument, a string containing the text just inserted. - -This variable is buffer-local.") - -(defvar comint-input-sender (function comint-simple-send) - "Function to actually send to PROCESS the STRING submitted by user. -Usually this is just `comint-simple-send', but if your mode needs to -massage the input string, put a different function here. -`comint-simple-send' just sends the string plus a newline. -This is called from the user command `comint-send-input'.") - -(defcustom comint-eol-on-send t - "*Non-nil means go to the end of the line before sending input. -See `comint-send-input'." - :type 'boolean - :group 'comint) - -(defcustom comint-mode-hook '() - "Called upon entry into comint-mode -This is run before the process is cranked up." - :type 'hook - :group 'comint) - -;; This is initialized by the various language environments, do not -;; Custom-ize it. -(defvar comint-exec-hook '() - "Called each time a process is exec'd by `comint-exec'. -This is called after the process is cranked up. It is useful for things that -must be done each time a process is executed in a comint mode buffer (e.g., -`(process-kill-without-query)'). In contrast, the `comint-mode-hook' is only -executed once when the buffer is created.") - -(defvar comint-mode-map nil) - -(defvar comint-ptyp t - "Non-nil if communications via pty; false if by pipe. Buffer local. -This is to work around a bug in Emacs process signalling.") - -(defvar comint-input-ring nil) -(defvar comint-last-input-start) -(defvar comint-last-input-end) -(defvar comint-last-output-start) -(defvar comint-input-ring-index nil - "Index of last matched history element.") -(defvar comint-matching-input-from-input-string "" - "Input previously used to match input history.") - -(put 'comint-input-ring 'permanent-local t) -(put 'comint-input-ring-index 'permanent-local t) -(put 'comint-input-autoexpand 'permanent-local t) -(put 'comint-input-filter-functions 'permanent-local t) -(put 'comint-output-filter-functions 'permanent-local t) -(put 'comint-scroll-to-bottom-on-input 'permanent-local t) -(put 'comint-scroll-to-bottom-on-output 'permanent-local t) -(put 'comint-scroll-show-maximum-output 'permanent-local t) -(put 'comint-ptyp 'permanent-local t) - -(defvar comint-1-menubar-menu nil) -(defconst comint-1-menubar-menu-1 - (purecopy - '("Comint1" - ["Previous Matching Current Input" - comint-previous-matching-input-from-input t] - ["Next Matching Current Input" comint-next-matching-input-from-input t] - ["Previous Input" comint-previous-input t] - ["Next Input" comint-next-input t] - ["Previous Input Matching Regexp..." comint-previous-matching-input t] - ["Next Input Matching Regexp..." comint-next-matching-input t] - ["Backward Matching Input..." comint-backward-matching-input t] - ["Forward Matching Input..." comint-forward-matching-input t] - "---" - ["Copy Old Input" comint-copy-old-input t] - ["Kill Current Input" comint-kill-input t] - ["Show Current Output Group" comint-show-output t] - ["Show Maximum Output" comint-show-maximum-output t] - ["Goto Previous Prompt" comint-previous-prompt t] - ["Goto Next Prompt" comint-next-prompt t] - ["Kill Command Output" comint-kill-output t] - ))) - -(defvar comint-2-menubar-menu nil) -(defconst comint-2-menubar-menu-1 - (purecopy - '("Comint2" - ["Complete Before Point" comint-dynamic-complete t] - ["Complete File Name" comint-dynamic-complete-filename t] - ["File Completion Listing" comint-dynamic-list-filename-completions t] - ["Expand File Name" comint-replace-by-expanded-filename t] - ;; this is cheesy but the easiest way to get this. - ["Complete Env. Variable Name" shell-dynamic-complete-environment-variable - :active t :included (eq 'shell-mode major-mode)] - ["Expand Directory Reference" shell-replace-by-expanded-directory - :active t :included (eq 'shell-mode major-mode)] - "---" - ["Send INT" comint-interrupt-subjob t] - ["Send STOP" comint-stop-subjob t] - ["Send CONT" comint-continue-subjob t] - ["Send QUIT" comint-quit-subjob t] - ["Send KILL" comint-kill-subjob t] - ["Send EOF" comint-send-eof t] - ))) - -(defvar comint-history-menubar-menu nil) -(defconst comint-history-menubar-menu-1 - (purecopy - '("History" - :filter comint-history-menu-filter - ["Expand History Before Point" comint-replace-by-expanded-history - comint-input-autoexpand] - ["List Input History" comint-dynamic-list-input-ring t] - "---" - ))) - - -(defun comint-mode () - "Major mode for interacting with an inferior interpreter. -Interpreter name is same as buffer name, sans the asterisks. -Return at end of buffer sends line as input. -Return not at end copies rest of line to end and sends it. -Setting variable `comint-eol-on-send' means jump to the end of the line -before submitting new input. - -This mode is customised to create major modes such as Inferior Lisp -mode, Shell mode, etc. This can be done by setting the hooks -`comint-input-filter-functions', `comint-input-filter', `comint-input-sender' -and `comint-get-old-input' to appropriate functions, and the variable -`comint-prompt-regexp' to the appropriate regular expression. - -An input history is maintained of size `comint-input-ring-size', and -can be accessed with the commands \\[comint-next-input], \\[comint-previous-input], and \\[comint-dynamic-list-input-ring]. -Input ring history expansion can be achieved with the commands -\\[comint-replace-by-expanded-history] or \\[comint-magic-space]. -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', -`comint-dynamic-complete', `comint-dynamic-list-filename-completions', and -`comint-magic-space'. - -Input to, and output from, the subprocess can cause the window to scroll to -the end of the buffer. See variables `comint-output-filter-functions', -`comint-scroll-to-bottom-on-input', and `comint-scroll-to-bottom-on-output'. - -If you accidentally suspend your process, use \\[comint-continue-subjob] -to continue it. - -\\{comint-mode-map} - -Entry to this mode runs the hooks on `comint-mode-hook'." - (interactive) - ;; Do not remove this. All major modes must do this. - (kill-all-local-variables) - (setq major-mode 'comint-mode) - (setq mode-name "Comint") - (setq mode-line-process '(": %s")) ; XEmacs - (use-local-map comint-mode-map) - (make-local-variable 'comint-last-input-start) - (setq comint-last-input-start (make-marker)) - (set-marker comint-last-input-start (point-min)) - (make-local-variable 'comint-last-input-end) - (setq comint-last-input-end (make-marker)) - (set-marker comint-last-input-end (point-min)) - (make-local-variable 'comint-last-output-start) - (setq comint-last-output-start (make-marker)) - (make-local-variable 'comint-prompt-regexp) ; Don't set; default - (make-local-variable 'comint-input-ring-size) ; ...to global val. - (make-local-variable 'comint-input-ring) - (make-local-variable 'comint-input-ring-file-name) - (or (and (boundp 'comint-input-ring) comint-input-ring) - (setq comint-input-ring (make-ring comint-input-ring-size))) - (make-local-variable 'comint-input-ring-index) - (or (and (boundp 'comint-input-ring-index) comint-input-ring-index) - (setq comint-input-ring-index nil)) - (make-local-variable 'comint-matching-input-from-input-string) - (make-local-variable 'comint-input-autoexpand) - (make-local-variable 'comint-input-ignoredups) - (make-local-variable 'comint-delimiter-argument-list) - (make-local-hook 'comint-dynamic-complete-functions) - (make-local-variable 'comint-completion-fignore) - (make-local-variable 'comint-get-old-input) - (make-local-hook 'comint-input-filter-functions) - (make-local-variable 'comint-input-filter) - (make-local-variable 'comint-input-sender) - (make-local-variable 'comint-eol-on-send) - (make-local-variable 'comint-scroll-to-bottom-on-input) - (make-local-variable 'comint-scroll-to-bottom-on-output) - (make-local-variable 'comint-scroll-show-maximum-output) - (make-local-hook 'pre-command-hook) - (add-hook 'pre-command-hook 'comint-preinput-scroll-to-bottom nil t) - (make-local-hook 'comint-output-filter-functions) - (make-local-variable 'comint-ptyp) - (make-local-hook 'comint-exec-hook) - (make-local-variable 'comint-process-echoes) - (make-local-variable 'comint-file-name-quote-list) - (if (featurep 'menubar) - (progn - ;; make a local copy of the menubar, so our modes don't - ;; change the global menubar - ;; (set-buffer-menubar current-menubar) - ;; (add-submenu nil comint-1-menubar-menu) - (unless comint-1-menubar-menu - (easy-menu-define comint-1-menubar-menu nil "" - comint-1-menubar-menu-1)) - (easy-menu-add comint-1-menubar-menu) - ;; (add-submenu nil comint-2-menubar-menu) - (unless comint-2-menubar-menu - (easy-menu-define comint-2-menubar-menu nil "" - comint-2-menubar-menu-1)) - (easy-menu-add comint-2-menubar-menu) - ;; (add-submenu nil comint-history-menubar-menu))) - (unless comint-history-menubar-menu - (easy-menu-define comint-history-menubar-menu nil "" - comint-history-menubar-menu-1)) - (easy-menu-add comint-history-menubar-menu))) - (run-hooks 'comint-mode-hook)) - -(if comint-mode-map - nil - ;; Keys: - (setq comint-mode-map (make-sparse-keymap)) - (set-keymap-name comint-mode-map 'comint-mode-map) ; XEmacs - - ;; XEmacs - The FSF19 party line - ;;(define-key comint-mode-map "\ep" 'comint-previous-input) - ;;(define-key comint-mode-map "\en" 'comint-next-input) - - ;; The Lucid party line - (define-key comint-mode-map "\ep" 'comint-previous-matching-input-from-input) - (define-key comint-mode-map "\en" 'comint-next-matching-input-from-input) - (define-key comint-mode-map '(control up) - 'comint-previous-matching-input-from-input) - (define-key comint-mode-map '(control down) - 'comint-next-matching-input-from-input) - - (define-key comint-mode-map "\er" 'comint-previous-matching-input) - (define-key comint-mode-map "\es" 'comint-next-matching-input) - ;; XEmacs - alt-meta-anything is a horrible binding. Some keyboards don't have - ;; meta keys, so we use alt as meta. Consequently, alt-meta will not exist on - ;; all keyboards. Just blow this. These functions are on M-n and M-p. --stig - ;;(define-key comint-mode-map [?\A-\M-r] 'comint-previous-matching-input-from-input) - ;;(define-key comint-mode-map [?\A-\M-s] 'comint-next-matching-input-from-input) - ;; XEmacs: Yuck yuck. C-M-l has a perfectly good normal binding. - ;;(define-key comint-mode-map "\e\C-l" 'comint-show-output) - (define-key comint-mode-map "\C-m" 'comint-send-input) - ;; XEmacs - Use ^C^D instead of ^D. Jamie & Stig think this is too un-emacs. - ;;(define-key comint-mode-map "\C-d" 'comint-delchar-or-maybe-eof) - ;; XEmacs - FSF nuked this, but we're gonna keep it.... - (define-key comint-mode-map "\C-a" 'comint-bol) - ;; yuck, this is evil. - ;;(define-key comint-mode-map "\C-u" 'comint-universal-argument) ; XEmacs - (define-key comint-mode-map "\C-c\C-a" 'comint-bol) - (define-key comint-mode-map "\C-c\C-u" 'comint-kill-input) - (define-key comint-mode-map "\C-c\C-w" 'backward-kill-word) - (define-key comint-mode-map "\C-c\C-c" 'comint-interrupt-subjob) - (define-key comint-mode-map "\C-c\C-z" 'comint-stop-subjob) - (define-key comint-mode-map "\C-c\C-\\" 'comint-quit-subjob) - (define-key comint-mode-map "\C-c\C-m" 'comint-copy-old-input) - (define-key comint-mode-map "\C-c\C-o" 'comint-kill-output) - (define-key comint-mode-map "\C-c\C-r" 'comint-show-output) - (define-key comint-mode-map "\C-c\C-e" 'comint-show-maximum-output) - (define-key comint-mode-map "\C-c\C-l" 'comint-dynamic-list-input-ring) - (define-key comint-mode-map "\C-c\C-d" 'comint-send-eof) - - (define-key comint-mode-map "\C-c\C-n" 'comint-next-prompt) - (define-key comint-mode-map "\C-c\C-p" 'comint-previous-prompt) - ;; John Rose's suggestion - (define-key comint-mode-map "\e}" 'comint-next-prompt) - (define-key comint-mode-map "\e{" 'comint-previous-prompt) - - #-infodock (define-key comint-mode-map 'button3 'comint-popup-menu) - ) - -;;(defconst comint-popup-menu -;; '("Command Interpreter Commands" -;; ["Kill Command Output" comint-kill-output t] -;; ["Goto Next Prompt" comint-next-prompt t] -;; ["Goto Previous Prompt" comint-previous-prompt t] -;; ["Kill Input" comint-kill-input t] -;; "----" -;; ["Previous Input" comint-previous-matching-input-from-input t] -;; ["Next Input" comint-next-matching-input-from-input t] -;; ["Previous Input matching Regexp..." 'comint-previous-matching-input t] -;; ["Next Input matching Regexp..." 'comint-next-matching-input t] -;; ["List Command History" comint-dynamic-list-input-ring t] -;; "----" -;; ["Send INT" comint-interrupt-subjob t] -;; ["Send STOP" comint-stop-subjob t] -;; ["Send CONT" comint-continue-subjob t] -;; ["Send QUIT" comint-quit-subjob t] -;; ["Send KILL" comint-kill-subjob t] -;; ["Send EOF" comint-send-eof t] -;; )) - -(defun comint-popup-menu (event) - "Display the comint-mode menu." - (interactive "@e") - (let ((history (comint-make-history-menu))) - (popup-menu (if history - (append mode-popup-menu - (list "---" (cons "Command History" history))) - mode-popup-menu)))) - -(defcustom comint-history-menu-max 40 - "*Maximum number of entries to display on the Comint command-history menu." - :type 'integer - :group 'comint) - -(defun comint-history-menu-filter (menu) - (append menu (comint-make-history-menu))) - -(defun comint-make-history-menu () - (if (or (not (ringp comint-input-ring)) - (ring-empty-p comint-input-ring)) - nil - (let ((menu nil) - hist - (index (1- (ring-length comint-input-ring))) - (count 0)) - ;; We have to build up a list ourselves from the ring vector. - ;; We don't want the entries to get translated in a Mule - ;; environment, so we use the `suffix' field of the menu entries. - (while (and (>= index 0) - (and comint-history-menu-max - (< count comint-history-menu-max))) - (setq hist (ring-ref comint-input-ring index) - menu (cons (vector "" (list 'comint-menu-history hist) t hist) - menu) - count (1+ count) - index (1- index))) - menu))) - -(defun comint-menu-history (string) - (goto-char (point-max)) - (delete-region (process-mark (get-buffer-process (current-buffer))) (point)) - (insert string)) - -(defun comint-check-proc (buffer) - "Return t if there is a living process associated w/buffer BUFFER. -Living means the status is `open', `run', or `stop'. -BUFFER can be either a buffer or the name of one." - (let ((proc (get-buffer-process buffer))) - (and proc (memq (process-status proc) '(open run stop))))) - -;;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it () -;;; for the second argument (program). -;;;###autoload -(defun make-comint (name program &optional startfile &rest switches) - "Make a comint process NAME in a buffer, running PROGRAM. -The name of the buffer is made by surrounding NAME with `*'s. -PROGRAM should be either a string denoting an executable program to create -via `start-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP -connection to be opened via `open-network-stream'. If there is already a -running process in that buffer, it is not restarted. Optional third arg -STARTFILE is the name of a file to send the contents of to the process. - -If PROGRAM is a string, any more args are arguments to PROGRAM." - (or (fboundp 'start-process) - (error "Multiple processes are not supported for this system")) - (let ((buffer (get-buffer-create (concat "*" name "*")))) - ;; If no process, or nuked process, crank up a new one and put buffer in - ;; comint mode. Otherwise, leave buffer and existing process alone. - (cond ((not (comint-check-proc buffer)) - (save-excursion - (set-buffer buffer) - (comint-mode)) ; Install local vars, mode, keymap, ... - (comint-exec buffer name program startfile switches))) - buffer)) - -;;;###autoload -(defun comint-run (program) - "Run PROGRAM in a comint buffer and switch to it. -The buffer name is made by surrounding the file name of PROGRAM with `*'s. -The file name is used to make a symbol name, such as `comint-sh-hook', and any -hooks on this symbol are run in the buffer. -See `make-comint' and `comint-exec'." - (interactive "sRun program: ") - (let ((name (file-name-nondirectory program))) - (switch-to-buffer (make-comint name program)) - (run-hooks (intern-soft (concat "comint-" name "-hook"))))) - -(defun comint-exec (buffer name command startfile switches) - "Start up a process in buffer BUFFER for comint modes. -Blasts any old process running in the buffer. Doesn't set the buffer mode. -You can use this to cheaply run a series of processes in the same comint -buffer. The hook `comint-exec-hook' is run after each exec." - (save-excursion - (set-buffer buffer) - (let ((proc (get-buffer-process buffer))) ; Blast any old process. - (if proc (delete-process proc))) - ;; Crank up a new process - (let ((proc - (if (consp command) - (open-network-stream name buffer (car command) (cdr command)) - (comint-exec-1 name buffer command switches)))) - (set-process-filter proc 'comint-output-filter) - (make-local-variable 'comint-ptyp) - (setq comint-ptyp process-connection-type) ; T if pty, NIL if pipe. - ;; Jump to the end, and set the process mark. - (goto-char (point-max)) - (set-marker (process-mark proc) (point)) - ;; Feed it the startfile. - (cond (startfile - ;;This is guaranteed to wait long enough - ;;but has bad results if the comint does not prompt at all - ;; (while (= size (buffer-size)) - ;; (sleep-for 1)) - ;;I hope 1 second is enough! - (sleep-for 1) - (goto-char (point-max)) - (insert-file-contents startfile) - (setq startfile (buffer-substring (point) (point-max))) - (delete-region (point) (point-max)) - (comint-send-string proc startfile))) - (run-hooks 'comint-exec-hook) - buffer))) - -;;; This auxiliary function cranks up the process for comint-exec in -;;; the appropriate environment. - -(defun comint-exec-1 (name buffer command switches) - (let ((process-environment - (nconc - ;; If using termcap, we specify `emacs' as the terminal type - ;; because that lets us specify a width. - ;; If using terminfo, we specify `unknown' because that is - ;; a defined terminal type. `emacs' is not a defined terminal type - ;; and there is no way for us to define it here. - ;; Some programs that use terminfo get very confused - ;; if TERM is not a valid terminal type. - (if (and (boundp 'system-uses-terminfo) system-uses-terminfo) - (list "TERM=unknown" - (format "COLUMNS=%d" (frame-width))) - (list "TERM=emacs" - (format "TERMCAP=emacs:co#%d:tc=unknown:" (frame-width)))) - (if (getenv "EMACS") nil (list "EMACS=t")) - process-environment)) - (default-directory - (if (file-directory-p default-directory) - default-directory - "/"))) - (apply 'start-process name buffer command switches))) - -;;; Input history processing in a buffer -;;; =========================================================================== -;;; Useful input history functions, courtesy of the Ergo group. - -;;; Eleven commands: -;;; comint-dynamic-list-input-ring List history in help buffer. -;;; comint-previous-input Previous input... -;;; comint-previous-matching-input ...matching a string. -;;; comint-previous-matching-input-from-input ... matching the current input. -;;; comint-next-input Next input... -;;; comint-next-matching-input ...matching a string. -;;; comint-next-matching-input-from-input ... matching the current input. -;;; comint-backward-matching-input Backwards input... -;;; comint-forward-matching-input ...matching a string. -;;; comint-replace-by-expanded-history Expand history at point; -;;; replace with expanded history. -;;; comint-magic-space Expand history and insert space. -;;; -;;; Three functions: -;;; comint-read-input-ring Read into comint-input-ring... -;;; comint-write-input-ring Write to comint-input-ring-file-name. -;;; comint-replace-by-expanded-history-before-point Workhorse function. - -(defun comint-read-input-ring (&optional silent) - "Sets the buffer's `comint-input-ring' from a history file. -The name of the file is given by the variable `comint-input-ring-file-name'. -The history ring is of size `comint-input-ring-size', regardless of file size. -If `comint-input-ring-file-name' is nil this function does nothing. - -If the optional argument SILENT is non-nil, we say nothing about a -failure to read the history file. - -This function is useful for major mode commands and mode hooks. - -The structure of the history file should be one input command per line, -with the most recent command last. -See also `comint-input-ignoredups' and `comint-write-input-ring'." - (cond ((or (null comint-input-ring-file-name) - (equal comint-input-ring-file-name "")) - nil) - ((not (file-readable-p comint-input-ring-file-name)) - (or silent - (message "Cannot read history file %s" - comint-input-ring-file-name))) - (t - (let ((history-buf (get-buffer-create " *comint-history*")) - (file comint-input-ring-file-name) - (count 0) - (ring (make-ring comint-input-ring-size))) - (unwind-protect - (save-excursion - (set-buffer history-buf) - (widen) - (erase-buffer) - (insert-file-contents file) - ;; Save restriction in case file is already visited... - ;; Watch for those date stamps in history files! - (goto-char (point-max)) - (while (and (< count comint-input-ring-size) - (re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$" - nil t)) - (let ((history (buffer-substring (match-beginning 1) - (match-end 1)))) - (if (or (null comint-input-ignoredups) - (ring-empty-p ring) - (not (string-equal (ring-ref ring 0) history))) - (ring-insert-at-beginning ring history))) - (setq count (1+ count)))) - (kill-buffer history-buf)) - (setq comint-input-ring ring - comint-input-ring-index nil))))) - -(defun comint-write-input-ring () - "Writes the buffer's `comint-input-ring' to a history file. -The name of the file is given by the variable `comint-input-ring-file-name'. -The original contents of the file are lost if `comint-input-ring' is not empty. -If `comint-input-ring-file-name' is nil this function does nothing. - -Useful within process sentinels. - -See also `comint-read-input-ring'." - (cond ((or (null comint-input-ring-file-name) - (equal comint-input-ring-file-name "") - (null comint-input-ring) (ring-empty-p comint-input-ring)) - nil) - ((not (file-writable-p comint-input-ring-file-name)) - (message "Cannot write history file %s" comint-input-ring-file-name)) - (t - (let* ((history-buf (get-buffer-create " *Temp Input History*")) - (ring comint-input-ring) - (file comint-input-ring-file-name) - (index (ring-length ring))) - ;; Write it all out into a buffer first. Much faster, but messier, - ;; than writing it one line at a time. - (save-excursion - (set-buffer history-buf) - (erase-buffer) - (while (> index 0) - (setq index (1- index)) - (insert (ring-ref ring index) ?\n)) - (write-region (buffer-string) nil file nil 'no-message) - (kill-buffer nil)))))) - -;; XEmacs - FSF doesn't have this. -(defun comint-restore-window-config (conf &optional message) - ;; Don't obscure buffer being edited - (or (eq (selected-window) (minibuffer-window)) - (message "%s" (or message "Press space to flush"))) - (sit-for 0) - (if (if (fboundp 'next-command-event) - ;; lemacs - (let ((ch (next-command-event))) - (if (eq (event-to-character ch) ?\ ) - t - (progn (setq unread-command-event ch) - nil))) - ;; v19 FSFmacs - (let ((ch (read-event))) - (if (eq ch ?\ ) - t - (progn (setq unread-command-events (list ch)) - nil)))) - (set-window-configuration conf))) - - -(defun comint-dynamic-list-input-ring () - "List in help buffer the buffer's input history." - (interactive) - (if (or (not (ringp comint-input-ring)) - (ring-empty-p comint-input-ring)) - (message "No history") - (let ((history nil) - (history-buffer " *Input History*") - (index (1- (ring-length comint-input-ring))) - (conf (current-window-configuration))) - ;; We have to build up a list ourselves from the ring vector. - (while (>= index 0) - (setq history (cons (ring-ref comint-input-ring index) history) - index (1- index))) - ;; Change "completion" to "history reference" - ;; to make the display accurate. - (with-output-to-temp-buffer history-buffer - (display-completion-list history) - (set-buffer history-buffer) - (forward-line 3) - (let ((buffer-read-only nil)) - (while (search-backward "completion" nil 'move) - (replace-match "history reference")))) - (comint-restore-window-config conf)))) - -(defun comint-regexp-arg (prompt) - ;; Return list of regexp and prefix arg using PROMPT. - (let* ((minibuffer-history-sexp-flag nil) - ;; Don't clobber this. - (last-command last-command) - (regexp (read-from-minibuffer prompt nil nil nil - 'minibuffer-history-search-history))) - (list (if (string-equal regexp "") - (setcar minibuffer-history-search-history - (nth 1 minibuffer-history-search-history)) - regexp) - (prefix-numeric-value current-prefix-arg)))) - -(defun comint-search-arg (arg) - ;; First make sure there is a ring and that we are after the process mark - (cond ((not (comint-after-pmark-p)) - (error "Not at command line")) - ((or (null comint-input-ring) - (ring-empty-p comint-input-ring)) - (error "Empty input ring")) - ((zerop arg) - ;; arg of zero resets search from beginning, and uses arg of 1 - (setq comint-input-ring-index nil) - 1) - (t - arg))) - -(defun comint-search-start (arg) - ;; Index to start a directional search, starting at comint-input-ring-index - (if comint-input-ring-index - ;; If a search is running, offset by 1 in direction of arg - (mod (+ comint-input-ring-index (if (> arg 0) 1 -1)) - (ring-length comint-input-ring)) - ;; For a new search, start from beginning or end, as appropriate - (if (>= arg 0) - 0 ; First elt for forward search - (1- (ring-length comint-input-ring))))) ; Last elt for backward search - -(defun comint-previous-input-string (arg) - "Return the string ARG places along the input ring. -Moves relative to `comint-input-ring-index'." - (ring-ref comint-input-ring (if comint-input-ring-index - (mod (+ arg comint-input-ring-index) - (ring-length comint-input-ring)) - arg))) - -(defun comint-previous-input (arg) - "Cycle backwards through input history." - (interactive "*p") - (comint-previous-matching-input "." arg)) - -(defun comint-next-input (arg) - "Cycle forwards through input history." - (interactive "*p") - (comint-previous-input (- arg))) - -(defun comint-previous-matching-input-string (regexp arg) - "Return the string matching REGEXP ARG places along the input ring. -Moves relative to `comint-input-ring-index'." - (let* ((pos (comint-previous-matching-input-string-position regexp arg))) - (if pos (ring-ref comint-input-ring pos)))) - -(defun comint-previous-matching-input-string-position (regexp arg &optional start) - "Return the index matching REGEXP ARG places along the input ring. -Moves relative to START, or `comint-input-ring-index'." - (if (or (not (ringp comint-input-ring)) - (ring-empty-p comint-input-ring)) - (error "No history")) - (let* ((len (ring-length comint-input-ring)) - (motion (if (> arg 0) 1 -1)) - (n (mod (- (or start (comint-search-start arg)) motion) len)) - (tried-each-ring-item nil) - (prev nil)) - ;; Do the whole search as many times as the argument says. - (while (and (/= arg 0) (not tried-each-ring-item)) - ;; Step once. - (setq prev n - n (mod (+ n motion) len)) - ;; If we haven't reached a match, step some more. - (while (and (< n len) (not tried-each-ring-item) - (not (string-match regexp (ring-ref comint-input-ring n)))) - (setq n (mod (+ n motion) len) - ;; If we have gone all the way around in this search. - tried-each-ring-item (= n prev))) - (setq arg (if (> arg 0) (1- arg) (1+ arg)))) - ;; Now that we know which ring element to use, if we found it, return that. - (if (string-match regexp (ring-ref comint-input-ring n)) - n))) - -(defun comint-previous-matching-input (regexp arg) - "Search backwards through input history for match for REGEXP. -\(Previous history elements are earlier commands.) -With prefix argument N, search for Nth previous match. -If N is negative, find the next or Nth next match." - (interactive (comint-regexp-arg "Previous input matching (regexp): ")) - (setq arg (comint-search-arg arg)) - (let ((pos (comint-previous-matching-input-string-position regexp arg))) - ;; Has a match been found? - (if (null pos) - (error "Not found") - (setq comint-input-ring-index pos) - (message "History item: %d" (1+ pos)) - (delete-region - ;; Can't use kill-region as it sets this-command - (process-mark (get-buffer-process (current-buffer))) (point)) - (insert (ring-ref comint-input-ring pos))))) - -(defun comint-next-matching-input (regexp arg) - "Search forwards through input history for match for REGEXP. -\(Later history elements are more recent commands.) -With prefix argument N, search for Nth following match. -If N is negative, find the previous or Nth previous match." - (interactive (comint-regexp-arg "Next input matching (regexp): ")) - (comint-previous-matching-input regexp (- arg))) - -(defun comint-previous-matching-input-from-input (arg) - "Search backwards through input history for match for current input. -\(Previous history elements are earlier commands.) -With prefix argument N, search for Nth previous match. -If N is negative, search forwards for the -Nth following match." - (interactive "p") - (if (not (memq last-command '(comint-previous-matching-input-from-input - comint-next-matching-input-from-input))) - ;; Starting a new search - (setq comint-matching-input-from-input-string - (buffer-substring - (process-mark (get-buffer-process (current-buffer))) - (point)) - comint-input-ring-index nil)) - (comint-previous-matching-input - (concat "^" (regexp-quote comint-matching-input-from-input-string)) - arg)) - -(defun comint-next-matching-input-from-input (arg) - "Search forwards through input history for match for current input. -\(Following history elements are more recent commands.) -With prefix argument N, search for Nth following match. -If N is negative, search backwards for the -Nth previous match." - (interactive "p") - (comint-previous-matching-input-from-input (- arg))) - - -(defun comint-replace-by-expanded-history (&optional silent) - "Expand input command history references before point. -Expansion is dependent on the value of `comint-input-autoexpand'. - -This function depends on the buffer's idea of the input history, which may not -match the command interpreter's idea, assuming it has one. - -Assumes history syntax is like typical Un*x shells'. However, since emacs -cannot know the interpreter's idea of input line numbers, assuming it has one, -it cannot expand absolute input line number references. - -If the optional argument SILENT is non-nil, never complain -even if history reference seems erroneous. - -See `comint-magic-space' and `comint-replace-by-expanded-history-before-point'. - -Returns t if successful." - (interactive) - (if (and comint-input-autoexpand - (string-match "!\\|^\\^" (funcall comint-get-old-input)) - (save-excursion (beginning-of-line) - (looking-at comint-prompt-regexp))) - ;; Looks like there might be history references in the command. - (let ((previous-modified-tick (buffer-modified-tick))) - (message "Expanding history references...") - (comint-replace-by-expanded-history-before-point silent) - (/= previous-modified-tick (buffer-modified-tick))))) - - -(defun comint-replace-by-expanded-history-before-point (silent) - "Expand directory stack reference before point. -See `comint-replace-by-expanded-history'. Returns t if successful." - (save-excursion - (let ((toend (- (save-excursion (end-of-line nil) (point)) (point))) - (start (progn (comint-bol nil) (point)))) - ;; XEmacs - fsf has something weird and complex here that does the same thing. - (while (re-search-forward - "[!^]" (save-excursion (end-of-line nil) (- (point) toend)) t) - ;; This seems a bit complex. We look for references such as !!, !-num, - ;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^. - ;; If that wasn't enough, the plings can be suffixed with argument - ;; range specifiers. - ;; Argument ranges are complex too, so we hive off the input line, - ;; referenced with plings, with the range string to `comint-args'. - (setq comint-input-ring-index nil) - (goto-char (match-beginning 0)) ; XEmacs - (cond ((or (= (preceding-char) ?\\) - (comint-within-quotes start (point))) - ;; The history is quoted, or we're in quotes. - (goto-char (match-end 0))) ; XEmacs - ((looking-at "![0-9]+\\($\\|[^-]\\)") - ;; We cannot know the interpreter's idea of input line numbers. - (goto-char (match-end 0)) - (message "Absolute reference cannot be expanded")) - ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?") - ;; Just a number of args from `number' lines backward. - (let ((number (1- (string-to-number - (buffer-substring (match-beginning 1) - (match-end 1)))))) - (if (<= number (ring-length comint-input-ring)) - (progn - (replace-match - (comint-args (comint-previous-input-string number) - (match-beginning 2) (match-end 2)) - t t) - (setq comint-input-ring-index number) - (message "History item: %d" (1+ number))) - (goto-char (match-end 0)) - (message "Relative reference exceeds input history size")))) - ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!")) - ;; Just a number of args from the previous input line. - (replace-match - (comint-args (comint-previous-input-string 0) - (match-beginning 1) (match-end 1)) t t) - (message "History item: previous")) - ((looking-at - "!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?") - ;; Most recent input starting with or containing (possibly - ;; protected) string, maybe just a number of args. Phew. - (let* ((mb1 (match-beginning 1)) (me1 (match-end 1)) - (mb2 (match-beginning 2)) (me2 (match-end 2)) - (exp (buffer-substring (or mb2 mb1) (or me2 me1))) - (pref (if (save-match-data (looking-at "!\\?")) "" "^")) - (pos (save-match-data - (comint-previous-matching-input-string-position - (concat pref (regexp-quote exp)) 1)))) - (if (null pos) - (progn - (goto-char (match-end 0)) - (or silent - (progn (message "Not found") - (ding)))) - (setq comint-input-ring-index pos) - (replace-match - (comint-args (ring-ref comint-input-ring pos) - (match-beginning 4) (match-end 4)) - t t) - (message "History item: %d" (1+ pos))))) - ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?") - ;; Quick substitution on the previous input line. - (let ((old (buffer-substring (match-beginning 1) (match-end 1))) - (new (buffer-substring (match-beginning 2) (match-end 2))) - (pos nil)) - (replace-match (comint-previous-input-string 0) t t) - (setq pos (point)) - (goto-char (match-beginning 0)) - (if (not (search-forward old pos t)) - (or silent - (error "Not found")) - (replace-match new t t) - (message "History item: substituted")))) - (t - (goto-char (match-end 0)))))))) - - -(defun comint-magic-space (arg) - "Expand input history references before point and insert ARG spaces. -A useful command to bind to SPC. See `comint-replace-by-expanded-history'." - (interactive "p") - (comint-replace-by-expanded-history) - (self-insert-command arg)) - -(defun comint-within-quotes (beg end) - "Return t if the number of quotes between BEG and END is odd. -Quotes are single and double." - (let ((countsq (comint-how-many-region "\\(^\\|[^\\\\]\\)\'" beg end)) - (countdq (comint-how-many-region "\\(^\\|[^\\\\]\\)\"" beg end))) - (or (= (mod countsq 2) 1) (= (mod countdq 2) 1)))) - -(defun comint-how-many-region (regexp beg end) - "Return number of matches for REGEXP from BEG to END." - (let ((count 0)) - (save-excursion - (save-match-data - (goto-char beg) - (while (re-search-forward regexp end t) - (setq count (1+ count))))) - count)) - -(defun comint-args (string begin end) - ;; From STRING, return the args depending on the range specified in the text - ;; from BEGIN to END. If BEGIN is nil, assume all args. Ignore leading `:'. - ;; Range can be x-y, x-, -y, where x/y can be [0-9], *, ^, $. - (save-match-data - (if (null begin) - (comint-arguments string 0 nil) - (let* ((range (buffer-substring - (if (eq (char-after begin) ?:) (1+ begin) begin) end)) - (nth (cond ((string-match "^[*^]" range) 1) - ((string-match "^-" range) 0) - ((string-equal range "$") nil) - (t (string-to-number range)))) - (mth (cond ((string-match "[-*$]$" range) nil) - ((string-match "-" range) - (string-to-number (substring range (match-end 0)))) - (t nth)))) - (comint-arguments string nth mth))))) - -;; Return a list of arguments from ARG. Break it up at the -;; delimiters in comint-delimiter-argument-list. Returned list is backwards. -(defun comint-delim-arg (arg) - (if (null comint-delimiter-argument-list) - (list arg) - (let ((args nil) - (pos 0) - (len (length arg))) - (while (< pos len) - (let ((char (aref arg pos)) - (start pos)) - (if (memq char comint-delimiter-argument-list) - (while (and (< pos len) (eq (aref arg pos) char)) - (setq pos (1+ pos))) - (while (and (< pos len) - (not (memq (aref arg pos) - comint-delimiter-argument-list))) - (setq pos (1+ pos)))) - (setq args (cons (substring arg start pos) args)))) - args))) - -(defun comint-arguments (string nth mth) - "Return from STRING the NTH to MTH arguments. -NTH and/or MTH can be nil, which means the last argument. -Returned arguments are separated by single spaces. -We assume whitespace separates arguments, except within quotes. -Also, a run of one or more of a single character -in `comint-delimiter-argument-list' is a separate argument. -Argument 0 is the command name." - (let ((argpart "[^ \n\t\"'`]+\\|\\(\"[^\"]*\"\\|'[^']*'\\|`[^`]*`\\)") - (args ()) (pos 0) - (count 0) - beg str quotes) - ;; Build a list of all the args until we have as many as we want. - (while (and (or (null mth) (<= count mth)) - (string-match argpart string pos)) - (if (and beg (= pos (match-beginning 0))) - ;; It's contiguous, part of the same arg. - (setq pos (match-end 0) - quotes (or quotes (match-beginning 1))) - ;; It's a new separate arg. - (if beg - ;; Put the previous arg, if there was one, onto ARGS. - (setq str (substring string beg pos) - args (if quotes (cons str args) - (nconc (comint-delim-arg str) args)) - count (1+ count))) - (setq quotes (match-beginning 1)) - (setq beg (match-beginning 0)) - (setq pos (match-end 0)))) - (if beg - (setq str (substring string beg pos) - args (if quotes (cons str args) - (nconc (comint-delim-arg str) args)) - count (1+ count))) - (let ((n (or nth (1- count))) - (m (if mth (1- (- count mth)) 0))) - (mapconcat - (function (lambda (a) a)) (nthcdr n (nreverse (nthcdr m args))) " ")))) - -;;; -;;; Input processing stuff -;;; - -(defun comint-send-input () - "Send input to process. -After the process output mark, sends all text from the process mark to -point as input to the process. Before the process output mark, calls value -of variable `comint-get-old-input' to retrieve old input, copies it to the -process mark, and sends it. If variable `comint-process-echoes' is nil, -a terminal newline is also inserted into the buffer and sent to the process -\(if it is non-nil, all text from the process mark to point is deleted, -since it is assumed the remote process will re-echo it). - -Any history reference may be expanded depending on the value of the variable -`comint-input-autoexpand'. The list of function names contained in the value -of `comint-input-filter-functions' is called on the input before sending it. -The input is entered into the input history ring, if the value of variable -`comint-input-filter' returns non-nil when called on the input. - -If variable `comint-eol-on-send' is non-nil, then point is moved to the -end of line before sending the input. - -If variable `comint-append-old-input' is non-nil, then the results of -calling `comint-get-old-input' are appended to the end of the buffer. -The new input will combine with any partially-typed text already present -after the process output mark. Point is moved just before the newly -appended input, and a message is displayed prompting the user to type -\\[comint-send-input] again. - -The values of `comint-get-old-input', `comint-input-filter-functions' and -`comint-input-filter' are chosen according to the command interpreter running -in the buffer. E.g., - -If the interpreter is the csh, - comint-get-old-input is the default: take the current line, discard any - initial string matching regexp comint-prompt-regexp. - comint-input-filter-functions monitors input for \"cd\", \"pushd\", and - \"popd\" commands. When it sees one, it cd's the buffer. - comint-input-filter is the default: returns t if the input isn't all white - space. - -If the comint is Lucid Common Lisp, - comint-get-old-input snarfs the sexp ending at point. - comint-input-filter-functions does nothing. - comint-input-filter returns nil if the input matches input-filter-regexp, - which matches (1) all whitespace (2) :a, :c, etc. - -Similarly for Soar, Scheme, etc." - (interactive) - ;; Note that the input string does not include its terminal newline. - (let ((proc (get-buffer-process (current-buffer)))) - (if (not proc) (error "Current buffer has no process") - (let* ((pmark (process-mark proc)) - (pmark-val (marker-position pmark)) - ;; XEmacs - change by John Rose: confirm before sending input if - ;; not after process mark. - (append-here nil) - (intxt (if (>= (point) pmark-val) - (progn (if comint-eol-on-send (end-of-line)) - (buffer-substring pmark (point))) - (let ((copy (funcall comint-get-old-input))) - (push-mark) - (if (not comint-append-old-input) - (goto-char pmark-val) - (setq append-here (point-max)) - (goto-char append-here)) - (insert copy) - copy))) - (input (if (not (eq comint-input-autoexpand 'input)) - ;; Just whatever's already there - intxt - ;; Expand and leave it visible in buffer - (comint-replace-by-expanded-history t) - (buffer-substring pmark (point)))) - (history (if (not (eq comint-input-autoexpand 'history)) - (if (eq comint-input-autoexpand nil) - ;; XEmacs - nil means leave it alone! - input - (comint-arguments input 0 nil)) - ;; This is messy 'cos ultimately the original - ;; functions used do insertion, rather than return - ;; strings. We have to expand, then insert back. - (comint-replace-by-expanded-history t) - (let ((copy (buffer-substring pmark (point)))) - (delete-region pmark (point)) - (insert input) - (comint-arguments copy 0 nil))))) - (if append-here - (progn - (goto-char append-here) - (message - (substitute-command-keys - "(\\[comint-send-input] to confirm)"))) - (if comint-process-echoes - (delete-region pmark (point)) - (insert ?\n)) - (if (and (funcall comint-input-filter history) - (or (null comint-input-ignoredups) - (not (ringp comint-input-ring)) - (ring-empty-p comint-input-ring) - (not (string-equal (ring-ref comint-input-ring 0) - history)))) - (ring-insert comint-input-ring history)) - ;; XEmacs - run the input filters on the history instead - ;; of the input, so that the input sentinel is called on the - ;; history-expanded text and sees "cd foo" instead of "cd !$". - (run-hook-with-args 'comint-input-filter-functions - (concat history "\n")) - (setq comint-input-ring-index nil) - ;; Update the markers before we send the input - ;; in case we get output amidst sending the input. - (set-marker comint-last-input-start pmark) - (set-marker comint-last-input-end (point)) - (set-marker (process-mark proc) (point)) - (comint-input-done) - (funcall comint-input-sender proc input) - (comint-input-setup) - ;; XEmacs - A kludge to prevent the delay between insert and - ;; process output affecting the display. A case for a - ;; comint-send-input-hook? - (run-hook-with-args 'comint-output-filter-functions - (concat input "\n")) - (comint-output-filter proc "") - ))))) -(defun comint-input-done () - "Finalized comint-input-extent so nothing more is added." - (if (not comint-input-extent) - (comint-input-setup)) - (set-extent-property comint-input-extent 'start-closed nil) - (set-extent-property comint-input-extent 'end-closed nil) - (set-extent-property comint-input-extent 'detachable t) - ) - -(defun comint-input-setup () - "Insure the comint-input-extent is ready." - (require 'comint-xemacs) - (setq comint-input-extent (make-extent (point) (point-max))) - (set-extent-property comint-input-extent 'detachable nil) - (set-extent-property comint-input-extent 'start-closed t) - (set-extent-property comint-input-extent 'end-closed t) - (set-extent-face comint-input-extent 'comint-input-face) - ) - -(defvar comint-input-extent nil - "Current extent used for displaying text in buffer."); -(make-variable-buffer-local 'comint-input-extent) - -;; The purpose of using this filter for comint processes -;; is to keep comint-last-input-end from moving forward -;; when output is inserted. -(defun comint-output-filter (process string) - ;; First check for killed buffer - (let ((oprocbuf (process-buffer process))) - (if (and oprocbuf (buffer-name oprocbuf)) - (let ((obuf (current-buffer)) - (opoint nil) (obeg nil) (oend nil)) - (set-buffer oprocbuf) - (setq string (replace-in-string string "\^M" "") - opoint (point) - obeg (point-min) - oend (point-max)) - ;; Keep stuff being output (before input) from using input-extent - (if comint-input-extent - (set-extent-property comint-input-extent 'start-closed nil)) - (let ((buffer-read-only nil) - (nchars (length string)) - (ostart nil)) - (widen) - (goto-char (process-mark process)) - (setq ostart (point)) - (if (<= (point) opoint) - (setq opoint (+ opoint nchars))) - ;; Insert after old_begv, but before old_zv. - (if (< (point) obeg) - (setq obeg (+ obeg nchars))) - (if (<= (point) oend) - (setq oend (+ oend nchars))) - (insert-before-markers string) - ;; Don't insert initial prompt outside the top of the window. - (if (= (window-start (selected-window)) (point)) - (set-window-start (selected-window) (- (point) (length string)))) - (if (and comint-last-input-end - (marker-buffer comint-last-input-end) - (= (point) comint-last-input-end)) - (set-marker comint-last-input-end (- comint-last-input-end nchars))) - (set-marker comint-last-output-start ostart) - (set-marker (process-mark process) (point)) - (redraw-modeline)) - ;; Now insure everything inserted after (user input) is in extent - (if (not comint-input-extent) - (comint-input-setup)) - (set-extent-endpoints comint-input-extent (point) (point-max)) - (set-extent-property comint-input-extent 'start-closed t) - - (narrow-to-region obeg oend) - (goto-char opoint) - (run-hook-with-args 'comint-output-filter-functions string) - (set-buffer obuf))))) - -;; XEmacs - Use a variable for this so that new commands can be added easily. -(defvar comint-scroll-to-bottom-on-input-commands - '(self-insert-command - mouse-yank - mouse-yank-at-click - x-insert-selection - comint-previous-input - comint-next-input - comint-previous-matching-input - comint-next-matching-input - comint-previous-matching-input-from-input - comint-next-matching-input-from-input - ) - "List of functions which will cause the point to move to the end of comint buffers.") - -(defun comint-preinput-scroll-to-bottom () - "Go to the end of buffer in all windows showing it. -Movement occurs if point in the selected window is not after the process mark, -and `this-command' is an insertion command. Insertion commands recognised -are those in `comint-scroll-to-bottom-on-input-commands'. -Depends on the value of `comint-scroll-to-bottom-on-input'. - -This function should be a pre-command hook." - (if (and comint-scroll-to-bottom-on-input - (memq this-command comint-scroll-to-bottom-on-input-commands)) - (let* ((selected (selected-window)) - (current (current-buffer)) - (process (get-buffer-process current)) - (scroll comint-scroll-to-bottom-on-input)) - (if (and process (< (point) (process-mark process)) - scroll (not (window-minibuffer-p selected))) - (if (eq scroll 'this) - (goto-char (point-max)) - (walk-windows - (function (lambda (window) - (if (and (eq (window-buffer window) current) - (or (eq scroll t) (eq scroll 'all))) - ;; XEmacs - fsf does this the hard way. - (set-window-point window (point-max)) - ))) - 'not-minibuf t)))))) - -(defun comint-postoutput-scroll-to-bottom (string) - "Go to the end of buffer in all windows showing it. -Does not scroll if the current line is the last line in the buffer. -Depends on the value of `comint-scroll-to-bottom-on-output' and -`comint-scroll-show-maximum-output'. - -This function should be in the list `comint-output-filter-functions'." - (let* ((selected (selected-window)) - (current (current-buffer)) - (process (get-buffer-process current)) - (scroll comint-scroll-to-bottom-on-output)) - ;; XEmacs - don't select windows as they're walked. - (if process - (walk-windows - (function (lambda (window) - (if (eq (window-buffer window) current) - (progn - (if (and (< (window-point window) - (process-mark process)) - (or (eq scroll t) (eq scroll 'all) - ;; Maybe user wants point to jump to the end. - (and (eq scroll 'this) - (eq selected window)) - (and (eq scroll 'others) - (not (eq selected window))) - ;; If point was at the end, keep it at the end. - (>= (window-point window) - (- (process-mark process) (length string))))) - (set-window-point window (process-mark process))) - ;; Optionally scroll so that the text - ;; ends at the bottom of the window. - (if (and comint-scroll-show-maximum-output - (>= (window-point window) - (process-mark process)) - ;; XEmacs - lemacs addition - (not (pos-visible-in-window-p (point-max) window))) - (save-excursion - (set-window-point window (point-max)) - (recenter - ;; XEmacs - lemacs addition - (cond ((integerp comint-scroll-show-maximum-output) - comint-scroll-show-maximum-output) - ((floatp comint-scroll-show-maximum-output) - (floor (* (window-height window) - comint-scroll-show-maximum-output) - 1)) - (t - -1)) - window - ))) - )))) - nil t)))) - -(defun comint-truncate-buffer (&optional string) - "Truncate the buffer to `comint-buffer-maximum-size'. -This function could be on `comint-output-filter-functions' or bound to a key." - (interactive) - (save-excursion - (goto-char (point-max)) - (forward-line (- comint-buffer-maximum-size)) - (beginning-of-line) - (delete-region (point-min) (point)))) - -(defun comint-strip-ctrl-m (&optional string) - "Strip trailing `^M' characters from the current output group. -This function could be on `comint-output-filter-functions' or bound to a key." - (interactive) - (let ((pmark (process-mark (get-buffer-process (current-buffer))))) - (save-excursion - (goto-char - (if (interactive-p) comint-last-input-end comint-last-output-start)) - (while (re-search-forward "\r+$" pmark t) - (replace-match "" t t))))) -(defalias 'shell-strip-ctrl-m 'comint-strip-ctrl-m) - -(defun comint-show-maximum-output () - "Put the end of the buffer at the bottom of the window." - (interactive) - (goto-char (point-max)) - (recenter -1)) - -(defun comint-get-old-input-default () - "Default for `comint-get-old-input'. -Take the current line, and discard any initial text matching -`comint-prompt-regexp'." - (save-excursion - (beginning-of-line) - (comint-skip-prompt) - (let ((beg (point))) - (end-of-line) - (buffer-substring beg (point))))) - -(defun comint-copy-old-input () - "Insert after prompt old input at point as new input to be edited. -Calls `comint-get-old-input' to get old input." - (interactive) - (let ((input (funcall comint-get-old-input)) - (process (get-buffer-process (current-buffer)))) - (if (not process) - (error "Current buffer has no process") - (goto-char (process-mark process)) - (insert input)))) - -(defun comint-skip-prompt () - "Skip past the text matching regexp `comint-prompt-regexp'. -If this takes us past the end of the current line, don't skip at all." - (let ((eol (save-excursion (end-of-line) (point))) - ;; XEmacs - Arbitrary limit: prompt can be up to 10 lines long. - (search-limit (save-excursion (forward-line -10) (point)))) - (if (and (save-excursion - (goto-char eol) - (re-search-backward comint-prompt-regexp search-limit t)) - (<= (match-beginning 0) (point)) - (> (match-end 0) (point)) - (<= (match-end 0) eol)) - (goto-char (match-end 0))))) - -(defun comint-after-pmark-p () - "Return t if point is after the process output marker." - (let ((pmark (process-mark (get-buffer-process (current-buffer))))) - (<= (marker-position pmark) (point)))) - -(defun comint-simple-send (proc string) - "Default function for sending to PROC input STRING. -This just sends STRING plus a newline. To override this, -set the hook `comint-input-sender'." - (comint-send-string proc string) - (comint-send-string proc "\n")) - -;; XEmacs - fsf doesn't bind this to ^A, but we do. There is some merit to -;; their change, so we change the behavior of the function to act the same -;; as normal ^A unless we're after the process mark. For the old behavior, -;; use ^C^A as in FSF. --Stig -(defun comint-bol (arg) - "Goes to the beginning of line, then skips past the prompt, if any. -If prefix argument is given (\\[universal-argument]) the prompt is not skipped. - -The prompt skip is done by skipping text matching the regular expression -`comint-prompt-regexp', a buffer local variable." - (interactive "_P") - (let ((skip (and (null arg) - (or (not (eq (lookup-key global-map (this-command-keys)) - 'beginning-of-line)) - ;; If the buffer's process has gone bye-bye - ;; revert to being just beginning-of-line. - (not (get-buffer-process (current-buffer))) - (comint-after-pmark-p))))) - (beginning-of-line) - (if skip (comint-skip-prompt)))) - -;; XEmacs - more like an xterm interaction model... -(defun comint-universal-argument () - "Erase the current line of input, or begin a numeric argument. - -In buffers with interactive subprocesses, this modified version of -`universal-argument' erases the current line of user input just as ^U erases a -line of text at the UNIX command prompt. - -Otherwise, begin a numeric argument for the following command. -Digits or minus sign following \\[universal-argument] make up the numeric argument. -\\[universal-argument] following the digits or minus sign ends the argument. -\\[universal-argument] without digits or minus sign provides 4 as argument. -Repeating \\[universal-argument] without digits or minus sign - multiplies the argument by 4 each time." - (interactive) - (let ((proc (get-buffer-process (current-buffer)))) - (if (and proc (> (point) (process-mark proc))) - (progn (comint-bol nil) - (kill-region (point) (save-excursion (end-of-line) (point)))) - (let (key) - (setq key (read-key-sequence nil t)) - (while (equal (key-binding key) 'universal-argument) - (setq key (read-key-sequence nil t))))))) - -;;; 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, or add -;;; `comint-watch-for-password-prompt' to `comint-output-filter-functions'. - -;; XEmacs has a standard function for this. -(defun comint-read-noecho (prompt &optional stars) - "Read a password from the user. -See documentation of `read-passwd' for more info." - (read-passwd prompt)) - -(defun send-invisible (str) - "Read a string without echoing. -Then send it to the process running in the current buffer. A new-line -is additionally sent. String is not saved on comint input history list. -Security bug: your string can still be temporarily recovered with -\\[view-lossage]." - (interactive "P") ; Defeat snooping via C-x esc - (let ((proc (get-buffer-process (current-buffer)))) - (if (not proc) - (error "Current buffer has no process") - (comint-send-string - proc (if (stringp str) str (comint-read-noecho "Non-echoed text: " t))) - (comint-send-string proc "\n")))) - -(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'. - -This function could be in the list `comint-output-filter-functions'." - (if (string-match comint-password-prompt-regexp string) - (send-invisible nil))) - -;;; Low-level process communication - -(defalias 'comint-send-string 'process-send-string) -(defalias 'comint-send-region 'process-send-region) - -;;; Random input hackage - -(defun comint-kill-output () - "Kill all output from interpreter since last input. -Does not delete the prompt." - (interactive) - (let ((proc (get-buffer-process (current-buffer))) - (replacement nil)) - (save-excursion - (let ((pmark (progn (goto-char (process-mark proc)) - (beginning-of-line nil) - (point-marker)))) - ;; XEmacs - kill in case we want it back... - (kill-region comint-last-input-end pmark) - (goto-char (process-mark proc)) - (setq replacement (concat "*** output flushed ***\n" - (buffer-substring pmark (point)))) - (delete-region pmark (point)))) - ;; Output message and put back prompt - (comint-output-filter proc replacement))) - -;; XEmacs - don't move cursor unless necessary... -(defun comint-show-output () - "Display start of this batch of interpreter output at top of window. -Also put cursor there if the current position is not visible. -If the cursor is moved, then a mark is set at its old location." - (interactive) - (let ((pos (point))) - (goto-char (or (marker-position comint-last-input-end) (point-max))) - (beginning-of-line 0) - (set-window-start (selected-window) (point)) - (if (pos-visible-in-window-p pos) - (goto-char pos) - (save-excursion - (goto-char pos) - (push-mark)) - (comint-skip-prompt)))) - -(defun comint-interrupt-subjob () - "Interrupt the current subjob." - (interactive) - (interrupt-process nil comint-ptyp)) - -(defun comint-kill-subjob () - "Send kill signal to the current subjob." - (interactive) - (kill-process nil comint-ptyp)) - -(defun comint-quit-subjob () - "Send quit signal to the current subjob." - (interactive) - (quit-process nil comint-ptyp)) - -(defun comint-stop-subjob () - "Stop the current subjob. -WARNING: if there is no current subjob, you can end up suspending -the top-level process running in the buffer. If you accidentally do -this, use \\[comint-continue-subjob] to resume the process. (This -is not a problem with most shells, since they ignore this signal.)" - (interactive) - (stop-process nil comint-ptyp)) - -(defun comint-continue-subjob () - "Send CONT signal to process buffer's process group. -Useful if you accidentally suspend the top-level process." - (interactive) - (continue-process nil comint-ptyp)) - -(defun comint-kill-input () - "Kill all text from last stuff output by interpreter to point." - (interactive) - (let ((pmark (process-mark (get-buffer-process (current-buffer))))) - (if (> (point) (marker-position pmark)) - (kill-region pmark (point))))) - -(defun comint-delchar-or-maybe-eof (arg) - "Delete ARG characters forward, or (if at eob) send an EOF to subprocess." - (interactive "p") - (if (eobp) - (process-send-eof) - (delete-char arg))) - -(defun comint-send-eof () - "Send an EOF to the current buffer's process." - (interactive) - (process-send-eof)) - - -(defun comint-backward-matching-input (regexp arg) - "Search backward through buffer for match for REGEXP. -Matches are searched for on lines that match `comint-prompt-regexp'. -With prefix argument N, search for Nth previous match. -If N is negative, find the next or Nth next match." - (interactive (comint-regexp-arg "Backward input matching (regexp): ")) - (let* ((re (concat comint-prompt-regexp ".*" regexp)) - (pos (save-excursion (end-of-line (if (> arg 0) 0 1)) - (if (re-search-backward re nil t arg) - (point))))) - (if (null pos) - (progn (message "Not found") - (ding)) - (goto-char pos) - (comint-bol nil)))) - -(defun comint-forward-matching-input (regexp arg) - "Search forward through buffer for match for REGEXP. -Matches are searched for on lines that match `comint-prompt-regexp'. -With prefix argument N, search for Nth following match. -If N is negative, find the previous or Nth previous match." - (interactive (comint-regexp-arg "Forward input matching (regexp): ")) - (comint-backward-matching-input regexp (- arg))) - - -(defun comint-next-prompt (n) - "Move to end of Nth next prompt in the buffer. -See `comint-prompt-regexp'." - (interactive "_p") ; XEmacs - zmacs-regions - (let ((paragraph-start comint-prompt-regexp)) - (end-of-line (if (> n 0) 1 0)) - (forward-paragraph n) - (comint-skip-prompt))) - -(defun comint-previous-prompt (n) - "Move to end of Nth previous prompt in the buffer. -See `comint-prompt-regexp'." - (interactive "_p") ; XEmacs - (comint-next-prompt (- n))) - -;;; Support for source-file processing commands. -;;;============================================================================ -;;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have -;;; commands that process files of source text (e.g. loading or compiling -;;; files). So the corresponding process-in-a-buffer modes have commands -;;; for doing this (e.g., lisp-load-file). The functions below are useful -;;; for defining these commands. -;;; -;;; Alas, these guys don't do exactly the right thing for Lisp, Scheme -;;; and Soar, in that they don't know anything about file extensions. -;;; So the compile/load interface gets the wrong default occasionally. -;;; The load-file/compile-file default mechanism could be smarter -- it -;;; doesn't know about the relationship between filename extensions and -;;; whether the file is source or executable. If you compile foo.lisp -;;; with compile-file, then the next load-file should use foo.bin for -;;; the default, not foo.lisp. This is tricky to do right, particularly -;;; because the extension for executable files varies so much (.o, .bin, -;;; .lbin, .mo, .vo, .ao, ...). - - -;;; COMINT-SOURCE-DEFAULT -- determines defaults for source-file processing -;;; commands. -;;; -;;; COMINT-CHECK-SOURCE -- if FNAME is in a modified buffer, asks you if you -;;; want to save the buffer before issuing any process requests to the command -;;; interpreter. -;;; -;;; COMINT-GET-SOURCE -- used by the source-file processing commands to prompt -;;; for the file to process. - -;;; (COMINT-SOURCE-DEFAULT previous-dir/file source-modes) -;;;============================================================================ -;;; This function computes the defaults for the load-file and compile-file -;;; commands for tea, soar, cmulisp, and cmuscheme modes. -;;; -;;; - PREVIOUS-DIR/FILE is a pair (directory . filename) from the last -;;; source-file processing command. NIL if there hasn't been one yet. -;;; - SOURCE-MODES is a list used to determine what buffers contain source -;;; files: if the major mode of the buffer is in SOURCE-MODES, it's source. -;;; Typically, (lisp-mode) or (scheme-mode). -;;; -;;; If the command is given while the cursor is inside a string, *and* -;;; the string is an existing filename, *and* the filename is not a directory, -;;; then the string is taken as default. This allows you to just position -;;; your cursor over a string that's a filename and have it taken as default. -;;; -;;; If the command is given in a file buffer whose major mode is in -;;; SOURCE-MODES, then the filename is the default file, and the -;;; file's directory is the default directory. -;;; -;;; If the buffer isn't a source file buffer (e.g., it's the process buffer), -;;; then the default directory & file are what was used in the last source-file -;;; processing command (i.e., PREVIOUS-DIR/FILE). If this is the first time -;;; the command has been run (PREVIOUS-DIR/FILE is nil), the default directory -;;; is the cwd, with no default file. (\"no default file\" = nil) -;;; -;;; SOURCE-REGEXP is typically going to be something like (tea-mode) -;;; for T programs, (lisp-mode) for Lisp programs, (soar-mode lisp-mode) -;;; for Soar programs, etc. -;;; -;;; The function returns a pair: (default-directory . default-file). - -(defun comint-source-default (previous-dir/file source-modes) - (cond ((and buffer-file-name (memq major-mode source-modes)) - (cons (file-name-directory buffer-file-name) - (file-name-nondirectory buffer-file-name))) - (previous-dir/file) - (t - (cons default-directory nil)))) - - -;;; (COMINT-CHECK-SOURCE fname) -;;;============================================================================ -;;; Prior to loading or compiling (or otherwise processing) a file (in the CMU -;;; process-in-a-buffer modes), this function can be called on the filename. -;;; If the file is loaded into a buffer, and the buffer is modified, the user -;;; is queried to see if he wants to save the buffer before proceeding with -;;; the load or compile. - -(defun comint-check-source (fname) - (let ((buff (get-file-buffer fname))) - (if (and buff - (buffer-modified-p buff) - (y-or-n-p (format "Save buffer %s first? " (buffer-name buff)))) - ;; save BUFF. - (let ((old-buffer (current-buffer))) - (set-buffer buff) - (save-buffer) - (set-buffer old-buffer))))) - - -;;; (COMINT-GET-SOURCE prompt prev-dir/file source-modes mustmatch-p) -;;;============================================================================ -;;; COMINT-GET-SOURCE is used to prompt for filenames in command-interpreter -;;; commands that process source files (like loading or compiling a file). -;;; It prompts for the filename, provides a default, if there is one, -;;; and returns the result filename. -;;; -;;; See COMINT-SOURCE-DEFAULT for more on determining defaults. -;;; -;;; PROMPT is the prompt string. PREV-DIR/FILE is the (directory . file) pair -;;; from the last source processing command. SOURCE-MODES is a list of major -;;; modes used to determine what file buffers contain source files. (These -;;; two arguments are used for determining defaults). If MUSTMATCH-P is true, -;;; then the filename reader will only accept a file that exists. -;;; -;;; A typical use: -;;; (interactive (comint-get-source "Compile file: " prev-lisp-dir/file -;;; '(lisp-mode) t)) - -;;; This is pretty stupid about strings. It decides we're in a string -;;; if there's a quote on both sides of point on the current line. -(defun comint-extract-string () - "Return string around POINT that starts the current line, or nil." - (save-excursion - (let* ((point (point)) - (bol (progn (beginning-of-line) (point))) - (eol (progn (end-of-line) (point))) - (start (progn (goto-char point) - (and (search-backward "\"" bol t) - (1+ (point))))) - (end (progn (goto-char point) - (and (search-forward "\"" eol t) - (1- (point)))))) - (and start end - (buffer-substring start end))))) - -(defun comint-get-source (prompt prev-dir/file source-modes mustmatch-p) - (let* ((def (comint-source-default prev-dir/file source-modes)) - (stringfile (comint-extract-string)) - (sfile-p (and stringfile - (condition-case () - (file-exists-p stringfile) - (error nil)) - (not (file-directory-p stringfile)))) - (defdir (if sfile-p (file-name-directory stringfile) - (car def))) - (deffile (if sfile-p (file-name-nondirectory stringfile) - (cdr def))) - (ans (read-file-name (if deffile (format "%s(default %s) " - prompt deffile) - prompt) - defdir - (concat defdir deffile) - mustmatch-p))) - (list (expand-file-name (substitute-in-file-name ans))))) - -;;; I am somewhat divided on this string-default feature. It seems -;;; to violate the principle-of-least-astonishment, in that it makes -;;; the default harder to predict, so you actually have to look and see -;;; what the default really is before choosing it. This can trip you up. -;;; On the other hand, it can be useful, I guess. I would appreciate feedback -;;; on this. -;;; -Olin - - -;;; Simple process query facility. -;;; =========================================================================== -;;; This function is for commands that want to send a query to the process -;;; and show the response to the user. For example, a command to get the -;;; arglist for a Common Lisp function might send a "(arglist 'foo)" query -;;; to an inferior Common Lisp process. -;;; -;;; This simple facility just sends strings to the inferior process and pops -;;; up a window for the process buffer so you can see what the process -;;; responds with. We don't do anything fancy like try to intercept what the -;;; process responds with and put it in a pop-up window or on the message -;;; line. We just display the buffer. Low tech. Simple. Works good. - -;;; Send to the inferior process PROC the string STR. Pop-up but do not select -;;; a window for the inferior process so that its response can be seen. -(defun comint-proc-query (proc str) - (let* ((proc-buf (process-buffer proc)) - (proc-mark (process-mark proc))) - (display-buffer proc-buf) - (set-buffer proc-buf) ; but it's not the selected *window* - (let ((proc-win (get-buffer-window proc-buf)) - (proc-pt (marker-position proc-mark))) - (comint-send-string proc str) ; send the query - (accept-process-output proc) ; wait for some output - ;; Try to position the proc window so you can see the answer. - ;; This is bogus code. If you delete the (sit-for 0), it breaks. - ;; I don't know why. Wizards invited to improve it. - (if (not (pos-visible-in-window-p proc-pt proc-win)) - (let ((opoint (window-point proc-win))) - (set-window-point proc-win proc-mark) - (sit-for 0) - (if (not (pos-visible-in-window-p opoint proc-win)) - (push-mark opoint) - (set-window-point proc-win opoint))))))) - - -;;; Filename/command/history completion in a buffer -;;; =========================================================================== -;;; Useful completion functions, courtesy of the Ergo group. - -;;; Six commands: -;;; comint-dynamic-complete Complete or expand command, filename, -;;; history at point. -;;; 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; -;;; replace with expanded/completed name. -;;; comint-dynamic-simple-complete Complete stub given candidates. - -;;; These are not installed in the comint-mode keymap. But they are -;;; available for people who want them. Shell-mode installs them: -;;; (define-key shell-mode-map "\t" 'comint-dynamic-complete) -;;; (define-key shell-mode-map "\M-?" -;;; 'comint-dynamic-list-filename-completions))) -;;; -;;; Commands like this are fine things to put in load hooks if you -;;; want them present in specific modes. - -(defcustom comint-completion-autolist nil - "*If non-nil, automatically list possibilities on partial completion. -This mirrors the optional behavior of tcsh." - :type 'boolean - :group 'comint-completion) - -(defcustom comint-completion-addsuffix t - "*If non-nil, add a `/' to completed directories, ` ' to file names. -If a cons pair, it should be of the form (DIRSUFFIX . FILESUFFIX) where -DIRSUFFIX and FILESUFFIX are strings added on unambiguous or exact completion. -This mirrors the optional behavior of tcsh." - :type 'boolean - :group 'comint-completion) - -(defcustom comint-completion-recexact nil - "*If non-nil, use shortest completion if characters cannot be added. -This mirrors the optional behavior of tcsh. - -A non-nil value is useful if `comint-completion-autolist' is non-nil too." - :type 'boolean - :group 'comint-completion) - -(defcustom comint-completion-fignore nil - "*List of suffixes to be disregarded during file completion. -This mirrors the optional behavior of bash and tcsh. - -Note that this applies to `comint-dynamic-complete-filename' only." - :type '(repeat (string :tag "Suffix")) - :group 'comint-completion) - -(defvar comint-file-name-prefix "" - "Prefix prepended to absolute file names taken from process input. -This is used by comint's and shell's completion functions, and by shell's -directory tracking functions.") - -(defvar comint-file-name-quote-list nil - "List of characters to quote with `\' when in a file name. - -This is a good thing to set in mode hooks.") - - -(defun comint-directory (directory) - ;; Return expanded DIRECTORY, with `comint-file-name-prefix' if absolute. - (expand-file-name (if (file-name-absolute-p directory) - (concat comint-file-name-prefix directory) - directory))) - - -(defun comint-word (word-chars) - "Return the word of WORD-CHARS at point, or nil if non is found. -Word constituents are considered to be those in WORD-CHARS, which is like the -inside of a \"[...]\" (see `skip-chars-forward')." - (save-excursion - (let ((non-word-chars (concat "[^\\\\" word-chars "]")) (here (point))) - (while (and (re-search-backward non-word-chars nil 'move) - ;(memq (char-after (point)) shell-file-name-quote-list) - (eq (preceding-char) ?\\)) - (backward-char 1)) - ;; Don't go forward over a word-char (this can happen if we're at bob). - (if (or (not (bobp)) (looking-at non-word-chars)) - (forward-char 1)) - ;; Set match-data to match the entire string. - (if (< (point) here) - (progn (store-match-data (list (point) here)) - (match-string 0)))))) - -(defun comint-extract-current-pathname () - "Return the file name at point. -`@' or `.' are not valid characters at the end of the filename." - (save-excursion - (re-search-forward "@?\\([^-A-Za-z0-9_,/+%.~]\\|$\\)") - (goto-char (match-beginning 0)) - (re-search-backward - "[^-A-Za-z0-9_,/+%.@~][-A-Za-z0-9_,/+%.@~]+[-A-Za-z0-9_+%~]" - nil t) - (buffer-substring (1+ (match-beginning 0)) (match-end 0)))) - -(defun comint-match-partial-filename () - "Return the filename at point, or nil if none is found. -Environment variables are substituted. See `comint-word'." - (let ((filename (comint-word "~/A-Za-z0-9+@:_.$#%,={}-"))) - (and filename (substitute-in-file-name (comint-unquote-filename filename))))) - - -(defun comint-quote-filename (filename) - "Return FILENAME with magic characters quoted. -Magic characters are those in `comint-file-name-quote-list'." - (if (null comint-file-name-quote-list) - filename - (let ((regexp - (format "\\(^\\|[^\\]\\)\\([%s]\\)" - (mapconcat 'char-to-string comint-file-name-quote-list "")))) - (save-match-data - (while (string-match regexp filename) - (setq filename (replace-match "\\1\\\\\\2" nil nil filename))) - filename)))) - -(defun comint-unquote-filename (filename) - "Return FILENAME with quoted characters unquoted." - (if (null comint-file-name-quote-list) - filename - (save-match-data - (while (string-match "\\\\\\(.\\)" filename) - (setq filename (replace-match "\\1" nil nil filename))) - filename))) - - -;;;###autoload -(defun comint-dynamic-complete () - "Dynamically perform completion at point. -Calls the functions in `comint-dynamic-complete-functions' to perform -completion until a function returns non-nil, at which point completion is -assumed to have occurred." - (interactive) - (run-hook-with-args-until-success 'comint-dynamic-complete-functions)) - - -(defun comint-dynamic-complete-filename () - "Dynamically complete the filename at point. -Completes if after a filename. See `comint-match-partial-filename' and -`comint-dynamic-complete-as-filename'. -This function is similar to `comint-replace-by-expanded-filename', except that -it won't change parts of the filename already entered in the buffer; it just -adds completion characters to the end of the filename. A completions listing -may be shown in a help buffer if completion is ambiguous. - -Completion is dependent on the value of `comint-completion-addsuffix', -`comint-completion-recexact' and `comint-completion-fignore', and the timing of -completions listing is dependent on the value of `comint-completion-autolist'. - -Returns t if successful." - (interactive) - (if (comint-match-partial-filename) - (prog2 (or (window-minibuffer-p (selected-window)) - (message "Completing file name...")) - (comint-dynamic-complete-as-filename)))) - - -(defun comint-dynamic-complete-as-filename () - "Dynamically complete at point as a filename. -See `comint-dynamic-complete-filename'. Returns t if successful." - (let* ((completion-ignore-case nil) - (completion-ignored-extensions comint-completion-fignore) - (file-name-handler-alist nil) - (minibuffer-p (window-minibuffer-p (selected-window))) - (success t) - (dirsuffix (cond ((not comint-completion-addsuffix) "") - ((not (consp comint-completion-addsuffix)) "/") - (t (car comint-completion-addsuffix)))) - (filesuffix (cond ((not comint-completion-addsuffix) "") - ((not (consp comint-completion-addsuffix)) " ") - (t (cdr comint-completion-addsuffix)))) - (filename (or (comint-match-partial-filename) "")) - (pathdir (file-name-directory filename)) - (pathnondir (file-name-nondirectory filename)) - (directory (if pathdir (comint-directory pathdir) default-directory)) - (completion (file-name-completion pathnondir directory))) - (cond ((null completion) - (if minibuffer-p (ding) (message "No completions of %s" filename)) - (setq success nil)) - ((eq completion t) ; Means already completed "file". - (insert filesuffix) - (or minibuffer-p (message "Sole completion"))) - ((string-equal completion "") ; Means completion on "directory/". - (comint-dynamic-list-filename-completions)) - (t ; Completion string returned. - (let ((file (concat (file-name-as-directory directory) completion))) - (insert (comint-quote-filename - (substring (directory-file-name completion) - (length pathnondir)))) - (cond ((symbolp (file-name-completion completion directory)) - ;; We inserted a unique completion. - (insert (if (file-directory-p file) dirsuffix filesuffix)) - (or minibuffer-p (message "Completed"))) - ((and comint-completion-recexact comint-completion-addsuffix - (string-equal pathnondir completion) - (file-exists-p file)) - ;; It's not unique, but user wants shortest match. - (insert (if (file-directory-p file) dirsuffix filesuffix)) - (or minibuffer-p (message "Completed shortest"))) - ((or comint-completion-autolist - (string-equal pathnondir completion)) - ;; It's not unique, list possible completions. - (comint-dynamic-list-filename-completions)) - (t - (or minibuffer-p (message "Partially completed"))))))) - success)) - - -(defun comint-replace-by-expanded-filename () - "Dynamically expand and complete the filename at point. -Replace the filename with an expanded, canonicalised and completed replacement. -\"Expanded\" means environment variables (e.g., $HOME) and `~'s are replaced -with the corresponding directories. \"Canonicalised\" means `..' and `.' are -removed, and the filename is made absolute instead of relative. For expansion -see `expand-file-name' and `substitute-in-file-name'. For completion see -`comint-dynamic-complete-filename'." - (interactive) - (replace-match (expand-file-name (comint-match-partial-filename)) t t) - (comint-dynamic-complete-filename)) - - -(defun comint-dynamic-simple-complete (stub candidates) - "Dynamically complete STUB from CANDIDATES list. -This function inserts completion characters at point by completing STUB from -the strings in CANDIDATES. A completions listing may be shown in a help buffer -if completion is ambiguous. - -Returns nil if no completion was inserted. -Returns `sole' if completed with the only completion match. -Returns `shortest' if completed with the shortest of the completion matches. -Returns `partial' if completed as far as possible with the completion matches. -Returns `listed' if a completion listing was shown. - -See also `comint-dynamic-complete-filename'." - (let* ((completion-ignore-case nil) - (suffix (cond ((not comint-completion-addsuffix) "") - ((not (consp comint-completion-addsuffix)) " ") - (t (cdr comint-completion-addsuffix)))) - (candidates (mapcar (function (lambda (x) (list x))) candidates)) - (completions (all-completions stub candidates))) - (cond ((null completions) - (message "No completions of %s" stub) - nil) - ((= 1 (length completions)) ; Gotcha! - (let ((completion (car completions))) - (if (string-equal completion stub) - (message "Sole completion") - (insert (substring completion (length stub))) - (message "Completed")) - (insert suffix) - 'sole)) - (t ; There's no unique completion. - (let ((completion (try-completion stub candidates))) - ;; Insert the longest substring. - (insert (substring completion (length stub))) - (cond ((and comint-completion-recexact comint-completion-addsuffix - (string-equal stub completion) - (member completion completions)) - ;; It's not unique, but user wants shortest match. - (insert suffix) - (message "Completed shortest") - 'shortest) - ((or comint-completion-autolist - (string-equal stub completion)) - ;; It's not unique, list possible completions. - (comint-dynamic-list-completions completions) - 'listed) - (t - (message "Partially completed") - 'partial))))))) - - -(defun comint-dynamic-list-filename-completions () - "List in help buffer possible completions of the filename at point." - (interactive) - (let* ((completion-ignore-case nil) - (file-name-handler-alist nil) - (filename (or (comint-match-partial-filename) "")) - (pathdir (file-name-directory filename)) - (pathnondir (file-name-nondirectory filename)) - (directory (if pathdir (comint-directory pathdir) default-directory)) - (completions (file-name-all-completions pathnondir directory))) - (if (not completions) - (message "No completions of %s" filename) - (comint-dynamic-list-completions - (mapcar 'comint-quote-filename completions))))) - - -;;;###autoload -(defun comint-dynamic-list-completions (completions) - "List in help buffer sorted COMPLETIONS. -Typing SPC flushes the help buffer." - (let ((conf (current-window-configuration))) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list (sort completions 'string-lessp))) - ;; XEmacs - centralize this - (comint-restore-window-config conf))) - -;; #### - FSFmacs doesn't have this and I'm not gonna nuke it just yet, but -;; it seems awfully redundant to have this here when compile.el does pretty -;; much the same thing. --Stig - -;;; Filename and source location extraction from a buffer. -;;; lemacs change by John Rose -;;; =========================================================================== -;;; Functions for recognizing and extracting file names and line numbers. -;;; C-c C-f attempts to extract a location from the current line, and -;;; go to that location. - -;;; One command: -;;; comint-find-source-code Extract source location and follow it. - -;;; This should be installed globally, since file names and source locations -;;; are ubiquitous. However, don't overwrite an existing key binding. -(if (not (lookup-key global-map "\C-c\C-f")) - (global-set-key "\C-c\C-f" 'comint-find-source-code)) - -;;; Utility functions: -;;; comint-extract-source-location Parse source loc. from buffer or string. -;;; comint-extract-current-pathname Extract potential pathname around point. -;;; comint-match-partial-pathname Match a potential pathname before point. - -(defconst comint-source-location-patterns - '(;; grep (and cpp): file.c: 10: - ("\\(^\\|[ \t]\\)\\([^ \t\n]+\\): *\\([0-9]+\\):[ \t]*\\(.*\\)" (grep cpp) (2 3 4)) - ;; cpp: #line 10 "file.c" - ("#\\(line\\)? *\\([0-9]+\\) *\"\\([^\"\n]+\\)\"" cpp (3 2)) - ;; cc: "file.c", line 10 - ("\"\\([^\"\n]+\\)\", line +\\([0-9]+\\)\\(:[ \t]+\\(.*\\)\\)?" cc (1 2 4)) - ;; f77: line 10 of file.c - ("line +\\([0-9]+\\) +of +\\([^ \t\n]+\\)\\(:[ \t]+\\(.*\\)\\)?" f77 (2 1 4)) - ;; perl: ...at file.c line 10. - ;; perl: ...at file.c line 10, near "foo" - ("^\\(.*\\) at \\([^ \t\n]+\\) line +\\([0-9]+\\)\\(\\.$\\|, \\)" - perl (2 3 1)) - ;; dbx: line 10 in "file.c" - ("\\(^\\(.*\\)[ \t]+at \\)?line +\\([0-9]+\\) +[in of file]+ +\"\\([^\"\n]+\\)\"" - dbx (4 3 2)) - ;; dbx: "file.c":10 - ("\"\\([^\"\n]+\\)\":\\([0-9]+\\)" dbx (1 2)) - ;; centerline: "file.c:10" - ("\"\\([^\"\n]+\\):\\([0-9]+\\)\"" centerline (1 2)) - ;; lint: : file.c(10) - (": *\\([^ \t\n)]+\\) *(\\([0-9]+\\))" lint (1 2)) - ;; lint: file.c(10) : - ("\\(^\\|[ \t]\\)\\([^ \t\n)]+\\) *(\\([0-9]+\\)) *:" lint (2 3)) - ;; lint: ( file.c(10) ) - ("( +\\([^ \t\n)]+\\) *(\\([0-9]+\\)) +)" lint (1 2)) - ;; troff: `file.c', line 10 - ("[\"`']\\([^\"`'\n]+\\)[\"`'], line +\\([0-9]+\\)" troff (1 2)) - ;; ri: "file.c" 10: - ("\"\\([^\"\n]+\\)\" *\\([0-9]+\\):" ri (1 2)) ;;Never heard of ri. - ;; mod: File file.c, line 10 - ("[Ff]ile +\\([^ \t\n]+\\), line +\\([0-9]+\\)" mod (1 2)) - ;; ksh: file.c[10] : - ("\\(^\\|[ \t]\\)\\([^ \t\n)]+\\) *\\[\\([0-9]+\\)\\] *:[ \t]+\\(.*\\)" - ksh (2 3 4)) - ;; shell: file.c: syntax error at line 10 - ("\\(^\\|[ \t]\\)\\([^ \t\n:]+\\):[ \t]+\\(.*\\)[ \t]+[, at]*line +\\([0-9]+\\)" - sh (2 4 3) -1) - ) - "Series of regexps matching file number locations. -Each list entry is a 3-list of a regexp, a program name, and up to 3 numbers. -The numbers name regexp fields which will hold the file, line number, -and associated diagnostic message (if any). -The program name is a symbol or list of symbols, and -is returned unexamined from `comint-extract-source-location'; -it should be a guess at who produced the message, e.g., 'cc'. - -In the case of multiple matches, `comint-extract-source-location' -will return the leftmost, longest match of the highest priority. -The priority of most patterns is 0, but a fourth element on -the list, if present, specifies a different priority. - -The regexps initially stored here are based on the one in compile.el -\(although the pattern containing 'of' must also contain 'line'). -They are also drawn from the Unix filters 'error' and 'fwarn'. -The patterns are known to recognize errors from the following -Un*x language processors: - cpp, cc, dbx, lex, f77, Centerline C, sh (Bourne), lint, mod -The following language processors do not incorporate file names -in every error message, and so are more difficult to accomodate: - yacc, pc, csh - ") - -(defun comint-extract-source-location (&optional start end commands markers) - "Return a 6-list of (file line command diagnostic mstart mend), -obtained by parsing the current buffer between START and END, -which default to the bounds of the current line. - -Use the list comint-source-location-patterns to guide parsing. - -The match returned will be on the latest line containing a match, but -will be the earliest possible match on that line. - -START can also be a string, in which case it inserted in the buffer -\"*Extract File and Line*\" and parsed there. - -COMMANDS is an optional list of pattern types, which has the effect of -temporarily reducing the list comint-source-location-patterns -to only those entries which apply to the given commands. - -Return NIL if there is no recognizable source location. - -MSTART and MEND give the limits of the matched source location. - -If MARKERS is true, return no strings, but rather cons cells -of the form (beg-marker . end-marker). -" - (if (not start) - (progn - (setq start (save-excursion (beginning-of-line) (point))) - (setq end (save-excursion (end-of-line) (point))))) - (if (stringp start) - (save-excursion - (set-buffer (get-buffer-create "*Extract File and Line*")) - (erase-buffer) - (insert start) - (comint-extract-source-location (point-min) (point-max) commands markers)) - (let ((ptr (if (and (consp commands) - (consp (car commands))) - (prog1 commands (setq commands nil)) - comint-source-location-patterns)) - pat - (found-bol (- (point-min) 1)) - (found-prio -999999) - found-beg - found-end - found-pat - found-data - set-found-data) - (setq set-found-data - (function (lambda (data) - (while found-data - (let ((m (car found-data))) - (if (markerp m) (set-marker m nil))) - (setq found-data (cdr found-data))) - (setq found-data data)))) - (if (and commands (not (listp commands))) - (setq commands (list commands))) - (save-excursion - (save-restriction - (narrow-to-region start end) - (while ptr - (setq pat (car ptr) ptr (cdr ptr)) - (goto-char (point-max)) - (if (and (or (null commands) - (if (consp (nth 1 pat)) - (member (nth 1 pat) commands) - ;; If (cadr pat) is a list, each list element - ;; is a command that might produce this. - (let ((ptr (nth 1 pat)) - (ismem nil)) - (while (and ptr (not ismem)) - (if (member (car ptr) commands) - (setq ismem t)) - (setq ptr (cdr ptr))) - ismem))) - (re-search-backward (nth 0 pat) found-bol t)) - (let (beg end bol prio) - (setq beg (match-beginning 0)) - (setq end (match-end 0)) - (beginning-of-line) - (setq bol (point)) - (re-search-forward (nth 0 pat)) - (if (> (match-beginning 0) beg) - (error "comint-extract-source-location botch")) - (setq beg (match-beginning 0)) - (setq end (match-end 0)) - (setq prio (or (nth 3 pat) 0)) - (if (or (> bol found-bol) - (and (= bol found-bol) - (or (> prio found-prio) - (and (= prio found-prio) - (or (< beg found-beg) - (and (= beg found-beg) - (> end found-end))))))) - (progn - (setq found-bol bol) - (setq found-prio prio) - (setq found-beg beg) - (setq found-end end) - (setq found-pat pat) - (funcall set-found-data (match-data))))))))) - (and found-data - (let* ((command (nth 1 found-pat)) - (fields (nth 2 found-pat)) - (f1 (nth 0 fields)) - (f2 (nth 1 fields)) - (f3 (nth 2 fields)) - (get-field - (function - (lambda (fn) - (and fn - (let ((beg (match-beginning fn)) - (end (match-end fn))) - (and beg end (> end beg) - (if markers - (cons (copy-marker beg) (copy-marker end)) - (buffer-substring beg end))))))))) - (store-match-data found-data) - (funcall set-found-data nil) - (let ((file (funcall get-field f1)) - (line (funcall get-field f2)) - (diagnostic (funcall get-field f3)) - (mstart (match-beginning 0)) - (mend (match-end 0))) - ;; (carefully use all match-data before calling string-match) - (list - file - (if (and (stringp line) - (prog1 - (string-match "\\`[0-9]+\\'" line) - (store-match-data found-data))) - (string-to-int line) - line) - command - diagnostic - mstart - mend - )))) - ))) - -;;; Commands for extracting source locations: - -(defcustom comint-find-source-code-max-lines 100 - "*Maximum number of lines to search backward for a source location, -when using \\[comint-find-source-code\\] with an interactive prefix." - :type 'integer - :group 'comint-source) - -(defcustom comint-find-source-file-hook nil - "*Function to call instead of comint-default-find-source-file -when comint-find-source-code parses out a file name and then wants to -visit its buffer. The sole argument is the file name. The function -must find the file, setting the current buffer, and return the file -name. It may also adjust the file name. If you change this variable, -make it buffer local." - :type 'function - :group 'comint-source) - -(defcustom comint-goto-source-line-hook nil - "*Function to call instead of comint-default-goto-source-line -after comint-find-source-code finds a file and then wants to -go to a line number mentioned in a source location. -The sole argument is the line number. The function must -return the line number, possibly adjusted. If you change -this variable, make it buffer local." - :type 'function - :group 'comint-source) - -(defun comint-find-source-code (multi-line) - "Search backward from point for a source location. -If a source location is found in the current line, -go to that location. - -If MULTI-LINE is false (this is the interactive prefix flag), -then only look for source locations in the current line. -Otherwise, look within comint-find-source-code-max-lines -before point. If a source location is found on a previous line, move -point to that location, so that another use of \\[comint-find-source-code\\] -will go to the indicated place. - -If no source location is found, then try to extract a filename -around the point, using comint-extract-current-pathname. - -In any case, if the file does not exist, prompt the user for -a pathname that does. Sometimes the file's directory needs -hand adjustment. - -This command uses comint-extract-source-location, which is customizable. -Also, once a source file and line have been extracted, it uses -comint-find-source-file-hook and comint-goto-source-line-hook -to interpret them." - (interactive "P") - (let* ((beg (save-excursion - (if multi-line - (forward-line (min 0 (- comint-find-source-code-max-lines))) - (beginning-of-line)) - (point))) - (end (save-excursion (end-of-line) (point))) - (res (or (comint-extract-source-location beg end) - (let ((file (comint-extract-current-pathname))) - (and file - (list file nil nil nil - (match-beginning 0) - (match-end 0)))) - (error "Not sitting on a source location.")))) - (let ((file (nth 0 res)) - (line (nth 1 res)) - ;;(cmd (nth 2 res)) - (info (nth 3 res)) - (mbeg (nth 4 res)) - (mend (nth 5 res)) - dofind) - (setq dofind - (not (and multi-line - mend - (< mend (save-excursion (beginning-of-line) (point)))))) - (if (not dofind) - (goto-char mbeg) - (progn - (setq file - (funcall (or comint-find-source-file-hook - 'comint-default-find-source-file) - file)) - (if line - (setq line - (funcall (or comint-goto-source-line-hook - 'comint-default-goto-source-line) - line))) - )) - (message "%s%s of %s%s%s" - (if dofind - "" (substitute-command-keys - "Hit \\[comint-find-source-code] for ")) - (cond ((null line) "current line") - ((numberp line) (format "line %s" line)) - (t line)) - (file-name-nondirectory file) - (if info ": " "") (or info ""))))) - - -(defun comint-default-find-source-file (file) - "Action taken by \\[comint-find-source-code] when find-source-file-hook is nil. -It calls substitute-in-file-name. If the file does not exist, it prompts -for the right pathname, using a similar pathname derived from a nearby -buffer as a default. It then calls find-file-other-window and returns the -amended file name." - (setq file (substitute-in-file-name file)) - (if (not (file-readable-p file)) - (setq file (comint-fixup-source-file-name file))) - (find-file-other-window file) - file) - -(defun comint-fixup-source-file-name (file) - (let (dir ptr nondir bfile res) - (setq nondir (file-name-nondirectory file)) - (setq ptr (buffer-list)) - (while (and ptr (not dir)) - (setq bfile (buffer-file-name (car ptr))) - (if (and bfile (equal (file-name-nondirectory bfile) nondir)) - (setq dir (file-name-directory bfile) - file (file-name-nondirectory bfile))) - (setq ptr (cdr ptr))) - (setq res - (read-file-name "Source file: " dir t nil file)) - (if (eq res t) - (expand-file-name file dir) - res))) - -(defun comint-default-goto-source-line (line) - "Action taken by \\[comint-find-source-code] when goto-source-line-hook is nil. -It widens & pushes the mark, then does goto-line in the current buffer. -It returns its line argument." - (widen) - (setq line (max line 0)) - (setq line (min line (+ 1 (count-lines (point-min) (point-max))))) - (push-mark) - (goto-line line) - line) - -;;; Converting process modes to use comint mode -;;; =========================================================================== -;;; The code in the Emacs 19 distribution has all been modified to use comint -;;; where needed. However, there are `third-party' packages out there that -;;; still use the old shell mode. Here's a guide to conversion. -;;; -;;; Renaming variables -;;; Most of the work is renaming variables and functions. These are the common -;;; ones: -;;; Local variables: -;;; last-input-start comint-last-input-start -;;; last-input-end comint-last-input-end -;;; shell-prompt-pattern comint-prompt-regexp -;;; shell-set-directory-error-hook -;;; Miscellaneous: -;;; shell-set-directory -;;; shell-mode-map comint-mode-map -;;; Commands: -;;; shell-send-input comint-send-input -;;; shell-send-eof comint-delchar-or-maybe-eof -;;; kill-shell-input comint-kill-input -;;; interrupt-shell-subjob comint-interrupt-subjob -;;; stop-shell-subjob comint-stop-subjob -;;; quit-shell-subjob comint-quit-subjob -;;; kill-shell-subjob comint-kill-subjob -;;; kill-output-from-shell comint-kill-output -;;; show-output-from-shell comint-show-output -;;; copy-last-shell-input Use comint-previous-input/comint-next-input -;;; -;;; SHELL-SET-DIRECTORY is gone, its functionality taken over by -;;; SHELL-DIRECTORY-TRACKER, the shell mode's comint-input-filter-functions. -;;; Comint mode does not provide functionality equivalent to -;;; shell-set-directory-error-hook; it is gone. -;;; -;;; comint-last-input-start is provided for modes which want to munge -;;; the buffer after input is sent, perhaps because the inferior -;;; insists on echoing the input. The LAST-INPUT-START variable in -;;; the old shell package was used to implement a history mechanism, -;;; but you should think twice before using comint-last-input-start -;;; for this; the input history ring often does the job better. -;;; -;;; If you are implementing some process-in-a-buffer mode, called foo-mode, do -;;; *not* create the comint-mode local variables in your foo-mode function. -;;; This is not modular. Instead, call comint-mode, and let *it* create the -;;; necessary comint-specific local variables. Then create the -;;; foo-mode-specific local variables in foo-mode. Set the buffer's keymap to -;;; be foo-mode-map, and its mode to be foo-mode. Set the comint-mode hooks -;;; (comint-{prompt-regexp, input-filter, input-filter-functions, -;;; get-old-input) that need to be different from the defaults. Call -;;; foo-mode-hook, and you're done. Don't run the comint-mode hook yourself; -;;; comint-mode will take care of it. The following example, from shell.el, -;;; is typical: -;;; -;;; (defvar shell-mode-map '()) -;;; (cond ((not shell-mode-map) -;;; (setq shell-mode-map (copy-keymap comint-mode-map)) -;;; (define-key shell-mode-map "\C-c\C-f" 'shell-forward-command) -;;; (define-key shell-mode-map "\C-c\C-b" 'shell-backward-command) -;;; (define-key shell-mode-map "\t" 'comint-dynamic-complete) -;;; (define-key shell-mode-map "\M-?" -;;; 'comint-dynamic-list-filename-completions))) -;;; -;;; (defun shell-mode () -;;; (interactive) -;;; (comint-mode) -;;; (setq comint-prompt-regexp shell-prompt-pattern) -;;; (setq major-mode 'shell-mode) -;;; (setq mode-name "Shell") -;;; (use-local-map shell-mode-map) -;;; (make-local-variable 'shell-directory-stack) -;;; (setq shell-directory-stack nil) -;;; (add-hook 'comint-input-filter-functions 'shell-directory-tracker) -;;; (run-hooks 'shell-mode-hook)) -;;; -;;; -;;; Note that make-comint is different from make-shell in that it -;;; doesn't have a default program argument. If you give make-shell -;;; a program name of NIL, it cleverly chooses one of explicit-shell-name, -;;; $ESHELL, $SHELL, or /bin/sh. If you give make-comint a program argument -;;; of NIL, it barfs. Adjust your code accordingly... -;;; -;;; Completion for comint-mode users -;;; -;;; For modes that use comint-mode, comint-dynamic-complete-functions is the -;;; hook to add completion functions to. Functions on this list should return -;;; non-nil if completion occurs (i.e., further completion should not occur). -;;; You could use comint-dynamic-simple-complete to do the bulk of the -;;; completion job. - - -;;; Do the user's customisation... - -(defvar comint-load-hook nil - "This hook is run when comint is loaded in. -This is a good place to put keybindings.") - -(run-hooks 'comint-load-hook) - - -(provide 'comint) - -;;; comint.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/custom-load.el --- a/lisp/comint/custom-load.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -;;; custom-load.el --- automatically extracted custom dependencies - - -;;; Code: - -(custom-add-loads 'ssh '("ssh")) -(custom-add-loads 'telnet '("telnet")) -(custom-add-loads 'shell '("shell")) -(custom-add-loads 'comint-completion '("comint")) -(custom-add-loads 'comint '("comint-xemacs" "comint" "telnet")) -(custom-add-loads 'rlogin '("rlogin")) -(custom-add-loads 'shell-faces '("shell")) -(custom-add-loads 'shell-directories '("shell")) -(custom-add-loads 'comint-source '("comint")) -(custom-add-loads 'processes '("background" "comint" "rlogin" "shell" "ssh")) -(custom-add-loads 'background '("background")) -(custom-add-loads 'unix '("rlogin" "shell" "ssh")) - -;;; custom-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/dbx.el --- a/lisp/comint/dbx.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -;;; dbx.el --- run dbx under Emacs - -;; Copyright (C) 1988 Free Software Foundation, Inc. - -;; Author: Masanobu UMEDA (umerin@flab.fujitsu.junet) -;; Keywords: c, unix, tools, debugging - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Code: - -(require 'comint) - -(defvar dbx-trace-flag nil - "Dbx trace switch.") - -(defvar dbx-process nil - "The process in which dbx is running.") - -(defvar dbx-break-point - "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\"" - "Regexp of pattern that dbx writes at break point.") - -(defvar inferior-dbx-mode-map nil) -(if inferior-dbx-mode-map - nil - (setq inferior-dbx-mode-map (make-sparse-keymap)) - (set-keymap-name inferior-dbx-mode-map 'inferior-dbx-mode-map) - (set-keymap-parent inferior-dbx-mode-map comint-mode-map) - (define-key inferior-dbx-mode-map "\C-c\C-w" 'dbx-where) - (define-key inferior-dbx-mode-map "\C-c\C-t" 'dbx-trace-mode) - (define-key ctl-x-map " " 'dbx-stop-at)) - -(defun inferior-dbx-mode () - "Major mode for interacting with an inferior dbx process. - -The following commands are available: -\\{inferior-dbx-mode-map} - -Entry to this mode calls the value of dbx-mode-hook with no arguments, -if that value is non-nil. Likewise with the value of comint-mode-hook. -dbx-mode-hook is called after comint-mode-hook. - -You can display the debugging program in other window and point out -where you are looking at using the command \\[dbx-where]. - -\\[dbx-trace-mode] toggles dbx-trace mode. In dbx-trace mode, -debugging program is automatically traced using output from dbx. - -The command \\[dbx-stop-at] sets break point at current line of the -program in the buffer. Major mode name of the buffer must be in -dbx-language-mode-list. - -Commands: - -Return at end of buffer sends line as input. -Return not at end copies line, sans any dbx prompt, to end and sends it. -\\[shell-send-eof] sends end-of-file as input. -\\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing. -\\[comint-interrupt-subjob] interrupts the shell or its current subjob if any. -\\[comint-stop-subjob] stops, likewise. \\[comint-quit-subjob] sends quit signal, likewise. -\\[dbx-where] displays debugging program in other window and - points out where you are looking at. -\\[dbx-trace-mode] toggles dbx-trace mode. -\\[dbx-stop-at] sets break point at current line." - (interactive) - (kill-all-local-variables) - (comint-mode) - (use-local-map inferior-dbx-mode-map) - (setq major-mode 'inferior-dbx-mode - mode-name "Inferior dbx" - comint-prompt-regexp "^[^)]*dbx) *") - (make-local-variable 'dbx-trace-flag) - (or (assq 'dbx-trace-flag minor-mode-alist) - (setq minor-mode-alist - (cons '(dbx-trace-flag " Trace") minor-mode-alist))) - (run-hooks 'dbx-mode-hook)) - -(defun run-dbx (path) - "Run inferior dbx process on PROGRAM, with I/O via buffer *dbx-PROGRAM*." - (interactive "fProgram to debug: ") - (setq path (expand-file-name path)) - (let ((file (file-name-nondirectory path))) - (switch-to-buffer (concat "*dbx-" file "*")) - (setq default-directory (file-name-directory path)) - (switch-to-buffer (make-comint (concat "dbx-" file) "dbx" nil file))) - (setq dbx-process (get-buffer-process (current-buffer))) - (set-process-filter dbx-process 'dbx-filter) - (inferior-dbx-mode)) - -(defun dbx-trace-mode (arg) - "Toggle dbx-trace mode. -With arg, turn dbx-trace mode on iff arg is positive. -In dbx-trace mode, user program is automatically traced." - (interactive "P") - (if (not (eql major-mode 'inferior-dbx-mode)) - (error "dbx-trace mode is effective in inferior-dbx mode only.")) - (setq dbx-trace-flag - (if (null arg) - (not dbx-trace-flag) - (> (prefix-numeric-value arg) 0))) - ;; Force mode line redisplay - (set-buffer-modified-p (buffer-modified-p))) - -(defun dbx-filter (process string) - "Trace debugging program automatically if dbx-trace-flag is not nil." - (save-excursion - (set-buffer (process-buffer process)) - (goto-char (point-max)) - (let ((beg (point))) - (insert-before-markers string) - (if dbx-trace-flag ;Trace mode is on? - (dbx-where beg t))) - (if (process-mark process) - (set-marker (process-mark process) (point-max)))) - (if (eq (process-buffer process) - (current-buffer)) - (goto-char (point-max))) - ) - -(defun dbx-where (&optional begin quiet) - "Display dbx'ed program in other window and point out where you are looking. -BEGIN bounds the search. If QUIET, just return nil (no error) if fail." - (interactive) - (let (file line) - (save-excursion - (if (re-search-backward dbx-break-point begin quiet) - (progn - (setq line (buffer-substring (match-beginning 1) (match-end 1))) - (setq file (buffer-substring (match-beginning 2) (match-end 2))) - ))) - (if (and file line) ;Find break point? - (progn - (find-file-other-window (expand-file-name file nil)) - (goto-line (string-to-int line)) ;Jump to the line - (beginning-of-line) - (setq overlay-arrow-string "=>") - (or overlay-arrow-position - (setq overlay-arrow-position (make-marker))) - (set-marker overlay-arrow-position (point) (current-buffer)) - (other-window 1)) ;Return to dbx - ))) - -(defun dbx-stop-at () - "Set break point at current line." - (interactive) - (let ((file-name (file-name-nondirectory buffer-file-name)) - (line (save-restriction - (widen) - (1+ (count-lines 1 (point)))))) - (process-send-string dbx-process - (concat "stop at \"" file-name "\":" line "\n")))) - -(provide 'dbx) - -;;; dbx.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/gdb-highlight.el --- a/lisp/comint/gdb-highlight.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1588 +0,0 @@ -;;; gdb-highlight.el --- make gdb buffers be mouse-sensitive. - -;;; Copyright (C) 1997 Jamie Zawinski - -;; Author: Jamie Zawinski -;; Created: 16-Apr-1997 -;; Version: 1.2 (17-May-97) -;; Keywords: extensions, c, unix, tools, debugging - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not synched. - -;;; Commentary: -;; -;; This package makes most objects printed in a *gdb* buffer be -;; mouse-sensitive: as text shows up in the buffer, it is parsed, -;; and objects which are recognized have context-sensitive commands -;; attached to them. Generally, the types that are noticed are: -;; -;; = function and method names; -;; = variable and parameter names; -;; = structure and object slots; -;; = source file names; -;; = type names; -;; = breakpoint numbers; -;; = stack frame numbers. -;; -;; Any time one of those objects is presented in the *gdb* buffer, -;; it will be mousable. Clicking middle mouse button (button2) on -;; it will take some default action -- edit the function, select -;; the stack frame, disable the breakpoint, etc. Clicking the right -;; mouse button (button3) will bring up a menu of commands, including -;; commands specific to the object under the mouse, or other objects -;; on the same line. -;; -;; In addition to these context-sensitive commands are more general -;; gdb commands which were previously inaccessible via the mouse -;; (listing breakpoints, returning values, etc); and the general -;; comint/shell-buffer commands which had been present before. -;; -;; If you notice an object being presented which could (usefully) -;; be made mouse sensitive, but which currently is not, please let -;; me know. - -;;; Installation: -;; -;; To install, add this to your .emacs file: -;; (add-hook 'gdb-mode-hook '(lambda () (require 'gdb-highlight))) - -;;; TODO: -;; -;; = It doesn't really work very well unless you've done `set width 0' -;; in your .gdbinit. It would be nice if this were fixed. -;; (And with `set width 0', `set print pretty on' is the way to go.) -;; -;; = In some contexts, the toggle-breakpoint command doesn't work, -;; because this code doesn't know whether it's enabled. It should -;; remember, or figure it out, or something. -;; -;; = Make it possible to edit the `keep' state of breakpoints. -;; -;; = Is it useful to make addresses clickable? If an address is -;; always acompanied by a variable, then no. -;; -;; = There has got to be a better way to implement `gdb-guess-file-name'. -;; -;; = Make some new toolbar icons and put the most common commands on it. -;; -;; = Maybe make gdb-toolbar-clear work more reliably by consulting a -;; breakpoint-number extent? -;; -;; = I want breakpoint icons in my source files, just like in Energize. -;; -;; = Add a command to quit-and-restart the debugger, with the same -;; breakpoints and program-arguments. (This wouldn't be interesting -;; if gdb didn't leak like a sieve...) -;; -;; = Figure out some way to realize when extents are no longer interesting -;; (stack frames and local variables that are no longer on the stack) -;; and make them no longer be mousable. This is tricky... Nuke them -;; whenever a "run" command is seen? -;; -;; = Make C-x SPC in a source buffer use gdb-menu-command so that it will -;; interrupt-and-continue the debugged program as necessary. -;; -;; = Do stuff for watchpoints (but I never use them, myself.) - -;;; WISHLIST: -;; -;; (extracted from my 13-May-1997 message to comp.emacs and -;; comp.emacs.xemacs, news:33785828.5A524730@netscape.com) -;; -;; 6.1. Make gdbsrc-mode not suck. -;; -;; The idea behind gdbsrc-mode is on the side of the angels: one -;; should be able to focus on the source code and not on the -;; debugger buffer, absolutely. But the implementation is just -;; awful. -;; -;; First and foremost, it should not change "modes" (in the more -;; general sense). Any commands that it defines should be on -;; keys which are exclusively used for that purpose, not keys -;; which are normally self-inserting. I can't be the only person -;; who usually has occasion to actually *edit* the sources which -;; the debugger has chosen to display! Switching into and out of -;; gdbsrc-mode is prohibitive. -;; -;; I want to be looking at my sources at all times, yet I don't -;; want to have to give up my source-editing gestures. I think -;; the right way to accomplish this is to put the gdbsrc commands -;; on the toolbar and on popup menus; or to let the user define -;; their own keys (I could see devoting my kp_enter key to -;; "step", or something common like that.) -;; -;; Also it's extremely frustrating that one can't turn off gdbsrc -;; mode once it has been loaded, without exiting and restarting -;; emacs; that alone means that I'd probably never take the time -;; to learn how to use it, without first having taken the time to -;; repair it... -;; -;; 6.2. Make it easier access to variable values. -;; -;; I want to be able to double-click on a variable name to -;; highlight it, and then drag it to the debugger window to have -;; its value printed. -;; -;; I want gestures that let me write as well as read: for -;; example, to store value A into slot B. -;; -;; 6.3. Make all breakpoints visible. -;; -;; Any time there is a running gdb which has breakpoints, the -;; buffers holding the lines on which those breakpoints are set -;; should have icons in them. These icons should be context- -;; sensitive: I should be able to pop up a menu to enable or -;; disable them, to delete them, to change their commands or -;; conditions. -;; -;; I should also be able to MOVE them. It's annoying when you -;; have a breakpoint with a complex condition or command on it, -;; and then you realize that you really want it to be at a -;; different location. I want to be able to drag-and-drop the -;; icon to its new home. -;; -;; 6.4. Make a debugger status display window. -;; -;; o I want a window off to the side that shows persistent -;; information -- it should have a pane which is a -;; drag-editable, drag-reorderable representation of the -;; elements on gdb's "display" list; they should be displayed -;; here instead of being just dumped in with the rest of the -;; output in the *gdb* buffer. -;; -;; o I want a pane that displays the current call-stack and -;; nothing else. I want a pane that displays the arguments -;; and locals of the currently-selected frame and nothing -;; else. I want these both to update as I move around on the -;; stack. -;; -;; Since the unfortunate reality is that excavating this -;; information from gdb can be slow, it would be a good idea -;; for these panes to have a toggle button on them which meant -;; "stop updating", so that when I want to move fast, I can, -;; but I can easily get the display back when I need it again. -;; -;; The reason for all of this is that I spend entirely too much -;; time scrolling around in the *gdb* buffer; with gdb-highlight, -;; I can just click on a line in the backtrace output to go to -;; that frame, but I find that I spend a lot of time *looking* -;; for that backtrace: since it's mixed in with all the other -;; random output, I waste time looking around for things (and -;; usually just give up and type "bt" again, then thrash around -;; as the buffer scrolls, and I try to find the lower frames that -;; I'm interested in, as they have invariably scrolled off the -;; window already... -;; -;; 6.5. Save and restore breakpoints across emacs/debugger sessions. -;; -;; This would be especially handy given that gdb leaks like a -;; sieve, and with a big program, I only get a few dozen -;; relink-and-rerun attempts before gdb has blown my swap space. -;; -;; 6.6. Keep breakpoints in sync with source lines. -;; -;; When a program is recompiled and then reloaded into gdb, the -;; breakpoints often end up in less-than-useful places. For -;; example, when I edit text which occurs in a file anywhere -;; before a breakpoint, emacs is aware that the line of the bp -;; hasn't changed, but just that it is in a different place -;; relative to the top of the file. Gdb doesn't know this, so -;; your breakpoints end up getting set in the wrong places -;; (usually the maximally inconvenient places, like *after* a -;; loop instead of *inside* it). But emacs knows, so emacs -;; should inform the debugger, and move the breakpoints back to -;; the places they were intended to be. -;; -;; (Possibly the OOBR stuff does some of this, but can't tell, -;; because I've never been able to get it to do anything but beep at -;; me and mumble about environments. I find it pretty funny that the -;; manual keeps explaining to me how intuitive it is, without -;; actually giving me a clue how to launch it...) - - -;;; Code: -;; -;; This code should be considered an example of how over-use of regular -;; expressions leads to code that is an unreadable, unmaintainable mess, -;; and why it's unfortunate that so much of emacs's speed depends on -;; their use, rather than on the use of more traditional parsers. - -(require 'gdb) - -(define-key gdb-mode-map 'button3 'gdb-popup-menu) -(defvar gdb-popup-menu - '("GDB Commands" - ["Up Stack" (gdb-menu-command "up" t) t] - ["Down Stack" (gdb-menu-command "down" t) t] - ["Next Line" (gdb-menu-command "next" t) t] - ["Next Line (Step In)" (gdb-menu-command "step" t) t] - ["Continue" (gdb-menu-command "continue" t) t] - ["Continue Until Return" (gdb-menu-command "finish" t) t] - ("Return..." - ["Return" (gdb-menu-command "return" t) t] - ["Return 0" (gdb-menu-command "return 0" t) t] - ["Return 1" (gdb-menu-command "return 1" t) t] - ["Return -1" (gdb-menu-command "return -1" t) t] - ["Return $" (gdb-menu-command "return $" t) t] - ) - "---" - ["Backtrace" (gdb-menu-command "backtrace" t) t] - ["List Breakpoints" (gdb-menu-command "info breakpoints" t) t] - ["List Local Variables" (gdb-menu-command "info locals" t) t] - ) - "Commands for the popup menu in gdb-mode. -The comint-popup-menu is appended to this, and certain context-sensitive -commands may be prepended to it, depending on the location of the mouse -when the `gdb-popup-menu' command is invoked.") - - -;;; Faces and keymaps used for mousable tokens in the *gdb* buffer. - -(defvar gdb-highlight-face 'gdb-highlight-face) ; the base face -(defvar gdb-breakpoint-number-face 'gdb-breakpoint-number-face) -;(defvar gdb-breakpoint-keep-face 'gdb-breakpoint-keep-face) -(defvar gdb-breakpoint-enabled-face 'gdb-breakpoint-enabled-face) -(defvar gdb-function-name-face 'gdb-function-name-face) -(defvar gdb-function-location-face 'gdb-function-location-face) -(defvar gdb-variable-name-face 'gdb-variable-name-face) -(defvar gdb-type-name-face 'gdb-type-name-face) - -(make-face 'gdb-highlight-face) -(or (face-differs-from-default-p 'gdb-highlight-face) - (make-face-italic 'gdb-highlight-face)) - -(let ((faces '(gdb-breakpoint-number-face - gdb-breakpoint-enabled-face - ;gdb-breakpoint-keep-face - gdb-function-name-face - gdb-function-location-face - gdb-variable-name-face - gdb-type-name-face))) - (while faces - (make-face (car faces)) - (or (face-differs-from-default-p (car faces)) - (if (fboundp 'set-face-parent) - (set-face-parent (car faces) 'gdb-highlight-face) - (copy-face 'gdb-highlight-face (car faces)))) - (setq faces (cdr faces)))) - - -(defvar gdb-token-map ; the base map, inherited by all. - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-token-map) - (define-key m 'button2 'undefined) - ;;(define-key m 'button3 'gdb-token-popup) - m)) - -(defvar gdb-breakpoint-number-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-breakpoint-number-map) - (set-keymap-parent m gdb-token-map) - ;; not sure if this is the most useful binding... maybe "delete" is better? - (define-key m 'button2 'gdb-mouse-disable-breakpoint) - m)) - -(defvar gdb-info-breakpoint-number-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-breakpoint-number-map) - (set-keymap-parent m gdb-token-map) - ;; not sure if this is the most useful binding... maybe "delete" is better? - (define-key m 'button2 'gdb-mouse-toggle-breakpoint-enabled) - m)) - -;(defvar gdb-breakpoint-keep-map -; (let ((m (make-sparse-keymap))) -; (set-keymap-name m 'gdb-breakpoint-keep-map) -; (set-keymap-parent m gdb-token-map) -; (define-key m 'button2 'gdb-token-mouse-toggle-keep) -; m)) - -(defvar gdb-breakpoint-enabled-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-breakpoint-enabled-map) - (set-keymap-parent m gdb-token-map) - (define-key m 'button2 'gdb-mouse-toggle-breakpoint-enabled) - m)) - -(defvar gdb-function-name-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-function-name-map) - (set-keymap-parent m gdb-token-map) - (define-key m 'button2 'gdb-mouse-edit-function) - m)) - -(defvar gdb-function-location-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-function-location-map) - (set-keymap-parent m gdb-token-map) - (define-key m 'button2 'gdb-mouse-edit-function-location) - m)) - -(defvar gdb-frame-number-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-frame-number-map) - (set-keymap-parent m gdb-token-map) - (define-key m 'button2 'gdb-mouse-goto-frame) - m)) - -(defvar gdb-variable-name-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-variable-name-map) - (set-keymap-parent m gdb-token-map) - (define-key m 'button2 'gdb-mouse-print-variable) - m)) - -(defvar gdb-type-name-map - (let ((m (make-sparse-keymap))) - (set-keymap-name m 'gdb-type-name-map) - (set-keymap-parent m gdb-token-map) - (define-key m 'button2 'gdb-mouse-print-type) - m)) - - -;;; Token definitions. - -;; These properties enumerate the faces and keymaps that will be put over -;; the tokens. - -(put 'gdb-frame-number-token 'gdb-token-face gdb-breakpoint-number-face) -(put 'gdb-frame-number-token 'gdb-token-keymap gdb-frame-number-map) - -;(put 'gdb-breakpoint-keep-token 'gdb-token-face gdb-breakpoint-keep-face) -;(put 'gdb-breakpoint-keep-token 'gdb-token-keymap gdb-breakpoint-keep-map) - -(put 'gdb-enabled-token 'gdb-token-face gdb-breakpoint-enabled-face) -(put 'gdb-enabled-token 'gdb-token-keymap gdb-breakpoint-enabled-map) - -(put 'gdb-function-name-token 'gdb-token-face gdb-function-name-face) -(put 'gdb-function-name-token 'gdb-token-keymap gdb-function-name-map) - -(put 'gdb-function-location-token 'gdb-token-face gdb-function-location-face) -(put 'gdb-function-location-token 'gdb-token-keymap gdb-function-location-map) - -(put 'gdb-breakpoint-number-token 'gdb-token-face gdb-breakpoint-number-face) -(put 'gdb-breakpoint-number-token 'gdb-token-keymap gdb-breakpoint-number-map) -(put 'gdb-info-breakpoint-number-token 'gdb-token-face - gdb-breakpoint-number-face) -(put 'gdb-info-breakpoint-number-token 'gdb-token-keymap - gdb-info-breakpoint-number-map) - -(put 'gdb-frame-number-token 'gdb-token-face gdb-breakpoint-number-face) -(put 'gdb-frame-number-token 'gdb-token-keymap gdb-frame-number-map) - -(put 'gdb-variable-name-token 'gdb-token-face gdb-variable-name-face) -(put 'gdb-variable-name-token 'gdb-token-keymap gdb-variable-name-map) - -(put 'gdb-type-name-token 'gdb-token-face gdb-type-name-face) -(put 'gdb-type-name-token 'gdb-token-keymap gdb-type-name-map) - - -;;; These regular expressions control what text corresponds to which tokens. - -(defconst gdb-highlight-token-patterns - ;; "May god forgive me for what I have unleashed." -- Evil Dead II. - (purecopy - (list - ;; Breakpoints output: - ;; - ;; Breakpoint 5, XCreateWindow () at Window.c:136 - ;; Breakpoint 6, foobar (x=0x7fff3000 "baz") at blorp.c:5382 - ;; - (list (concat "\\(Breakpoint " ; 1 - "\\([0-9]+\\)" ; .2 - "\\), " ; 1 - "\\(0x[0-9a-fA-F]+ in \\)?" ; 3 - "\\(" ; 4 - "\\([a-zA-Z0-9_]+\\):[a-zA-Z0-9_:~]+" ; .5 - "\\|" ; . - "[a-zA-Z0-9_]+" ; . - "\\)" ; 4 - "\\(" ; 6 - " *\\((.*)\\)" ; .7 - " at \\(" ; .8 - "\\([^ \t\n:]+\\):" ; ..9 - "\\([0-9]+\\)" ; ..10 - "\\)" ; .8 - "\\)?" ; 6 - ) - '(gdb-breakpoint-number-token ; 1 - nil ; 2 - nil ; 3 - gdb-function-name-token ; 4 (+5) - gdb-type-name-token ; 5 - nil ; 6 - gdb-arglist-token ; 7 - gdb-function-location-token ; 8 (9+10) - )) - - ;; Output of the "Break" command: - ;; - ;; Breakpoint 1 at 0x4881d4 - ;; Breakpoint 6 at 0xfa50f68: file cuexit.c, line 58. - ;; - (list (concat "\\(Breakpoint " ; 1 - "\\([0-9]+\\)" ; .2 - "\\) at " ; 1 - "\\(0x[0-9A-Fa-f]+\\)" ; 3 - "\\(: file " ; 4 - "\\(" ; .5 - "\\([^ \t\n:]+\\)" ; ..6 - ", line \\([0-9]+\\)" ; ..7 - "\\)" ; .5 - "\\)?" ; 4 - ) - '(gdb-breakpoint-number-token ; 1 - nil ; 2 - nil ;gdb-address-token ; 3 - nil ; 4 - gdb-function-location-token ; 5 (6+7) - )) - - ;; Note: breakpoint 5 (disabled) also set at pc 0x40b420. - ;; Note: breakpoint 5 also set at pc 0x40b420. - ;; - (list (concat "Note: " ; - "\\(breakpoint " ; 1 - "\\([0-9]+\\)" ; .2 - "\\)" ; 1 - ) - '(gdb-breakpoint-number-token ; 1 - nil ; 2 - )) - - ;; Stack Frames: - ;; - ;; 0xe1b8e0 in _OS_SELECT () at os_IRIX.s:50 - ;; XCreateWindow () at Window.c:136 - ;; #0 0x8e0db0 in _OS_SELECT () at os_IRIX.s:50 - ;; #0 XCreateWindow () at Window.c:136 - ;; Run till exit from #0 __ll_mul () at llmul.s:51 - ;; - (list (concat "\\(Run till exit from \\)?" ; 1 - "\\(" ; 2 - "#\\([0-9]+ *\\)" ; .3 - "\\)?" ; 2 - "\\(" ; 4 - "\\(0x[0-9A-Fa-f]+\\)" ; .5 - " in +\\)?" ; 4 - "\\(" ; 6 - "\\([a-zA-Z0-9_]+\\):[a-zA-Z0-9_:~]+" ; .7 - "\\|" ; 6 - "[a-zA-Z0-9_]+" ; - "\\) (" ; 6 - "\\(" ; 8 - "\\(.*\\)" ; .9 - "\\bat \\(" ; .10 - "\\([^ \t\n:]+\\):" ; ..11 - "\\([0-9]+\\)" ; ..12 - "\\)" ; .10 - "\\)?" ; 8 - ) - '(nil ; 1 - gdb-frame-number-token ; 2 - nil ; 3 - nil ; 4 - nil ;gdb-address-token ; 5 - gdb-function-name-token ; 6 (+7) - gdb-type-name-token ; 7 - nil ; 8 - gdb-arglist-token ; 9 - gdb-function-location-token ; 10 (11+12) - )) - - ;; Info Breakpoints output: - ;; - ;; 1 breakpoint keep y 0x0fa50f68 in exit at exit.c:58 - ;; 1 breakpoint keep y 0x000a1b00 - ;; 1 breakpoint keep y 0x0fa429ac <_write> - ;; 6 breakpoint keep y 0x00789490 in foo::bar(bad *) at x.cpp:99 - ;; 7 breakpoint keep y 0x00789490 - ;; - (list (concat "\\([0-9]+ *\\) " ; 1 - "\\(breakpoint *\\|watchpoint *\\) " ; 2 - "\\(keep *\\|del *\\|dis *\\) " ; 3 - "\\([yn] *\\) " ; 4 - "\\(0x[0-9A-Fa-f]+\\) *" ; 5 - "\\(in " ; 6 - "\\(" ; .7 - "[a-zA-Z0-9_]+" ; .. - "\\|" ; .7 - "\\([a-zA-Z0-9_]+\\):[a-zA-Z0-9_:~]+" ; ..8 - "\\)" ; .7 - "\\((.*)\\)?" ; 9 - " at " ; . - "\\(" ; .10 - "\\([^ \t\n:]+\\):" ; ..11 - "\\([0-9]+\\)" ; ..12 - "\\)" ; .10 - "\\|" ; 6 - "<" ; . - "\\(" ; .13 - "\\([a-zA-Z0-9_]+\\):[a-zA-Z0-9_:~]+" ; ..14 - "\\|" ; .13 - "[a-zA-Z0-9_]+" ; .. - "\\)" ; .13 - "\\((.*)\\)?" ; .15 - "[^>\n]*>" ; . - "\\)?" ; 6 - ) - '(gdb-info-breakpoint-number-token ; 1 - nil ; 2 - nil ;gdb-breakpoint-keep-token ; 3 - gdb-enabled-token ; 4 - nil ;gdb-address-token ; 5 - nil ; 6 - gdb-function-name-token ; 7 (+8) - gdb-type-name-token ; 8 - gdb-arglist-types-token ; 9 - gdb-function-location-token ; 10 (11+12) - nil ; 11 - nil ; 12 - gdb-function-name-token ; 13 - gdb-type-name-token ; 14 - gdb-arglist-types-token ; 15 - )) - - ;; Whatis and Ptype output: - ;; type = struct _WidgetRec * - ;; type = struct _WidgetRec { - ;; type = int () - ;; type = struct *(struct *, void *, void (*)()) - ;; type = struct foo *(struct foo *, unsigned char, int) - ;; type = unsigned int [4] - ;; - (list (concat "type = " - "\\(" ; 1 - "\\(signed \\|unsigned \\)?" ; .2 - "\\(struct \\|class \\|union \\|enum \\)?" ; .3 - "\\(?\\)" ; .4 - "\\)" ; 1 - "[ *]*" ; - "\\(" ; 5 - "{?$\\|" ; . - "\\[[0-9]*\\]$\\|" ; . - "\\((.*)\\)" ; .6 - "\\)" ; 5 - ) - '(gdb-type-name-token ; 1 (2+3+4) - nil ; 2 - nil ; 3 - nil ; 4 - nil ; 5 - gdb-arglist-types-token ; 6 - )) - - ;; Ptype output: - ;; CorePart core; - ;; void *constraints; - ;; short x; - ;; unsigned short width; - ;; struct *event_table; - ;; XtTMRec tm; - ;; void (*class_initialize)(); - ;; unsigned char (*set_values)(); - ;; unsigned char st_fstype[16]; - ;; type = enum {XtGeometryYes, XtGeometryNo, XtGeometryAlmost} - ;; - (list (concat " *" - "\\(" ; 1 - "\\(signed \\|unsigned \\)?" ; .2 - "\\(struct \\|class \\|union \\|enum \\)?" ; .3 - "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)" ; .4 - "\\)" ; 1 - "[ *]*" - "\\((\\**\\)?" ; 5 - "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)" ; 6 - "\\()()\\)?" ; 7 - "\\( *\\[[0-9]*\\]\\)?" ; 8 - "; *$" - ) - '(gdb-type-name-token ; 1 (2+3+4) - )) - - ;; Ptype output on C++ classes: - ;; - ;; virtual foo (int); - ;; unsigned int foo(void); - ;; static long unsigned int * foo(bar *, baz *, unsigned int); - ;; - ;; not handled: - ;; foo(bar *, _WidgetRec *, char const *, int); - ;; foo (foo &); - ;; foo & operator=(foo const &); - ;; - (list (concat " *" - "\\(static \\)?" ; 1 - "\\(" ; 2 - "\\(signed \\|unsigned " ; .3 - ;; #### not so sure about this: - "\\|long unsigned \\|short unsigned " ; .3 - "\\)?" ; .3 - "\\(struct \\|class \\|union \\|enum \\)?" ; .4 - "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)" ; .5 - "\\)" ; 1 - "[ *&]+" ; - " *\\([a-zA-Z_][a-zA-Z0-9_:]*\\)" ; 6 - " *\\((.*)\\)" ; 7 - "; *$" ; - ) - '(nil ; 1 - gdb-type-name-token ; 2 (3+4+5) - nil ; 3 - nil ; 4 - nil ; 5 - gdb-function-name-token ; 6 - gdb-arglist-types-token ; 7 - )) - - ;; Pointers to functions: - ;; - ;; $1 = {void ()} 0x4a1334 - ;; $2 = (void (*)()) 0x4a1334 - ;; - (list (concat ".* = " - "[({]" - "\\(" ; 1 - "\\(signed \\|unsigned \\)?" ; .2 - "\\(struct \\|class \\|union \\|enum \\)?" ; .3 - "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)" ; .4 - "\\)" ; 1 - " \\((\\*) ?\\)?" ; 5 - "\\((.*)\\)" ; 6 - "[)}] +" ; - "\\(0x[0-9A-Fa-f]+\\) +" ; 7 - "<\\([a-zA-Z_~][a-zA-Z0-9_:]*\\)" ; 8 - "\\+?[0-9]+?>" ; - ) - '(gdb-type-name-token ; 1 (2+3+4) - nil ; 2 - nil ; 3 - nil ; 4 - nil ; 5 - gdb-arglist-types-token ; 6 - nil ;gdb-address-token ; 7 - gdb-function-name-token ; 8 - )) - - ;; Local variables and structures: - ;; - ;; shell = (struct _WidgetRec *) 0x10267350 - ;; delete_response = 270955344 - ;; allow_resize = 200 'È' - ;; is_modal = 47 '/' - ;; class_name = 0xf661d40 "TopLevelShell", - ;; static foo = 0x10791ec0, - ;; initialize = 0xf684770 , - ;; av = {{ - ;; name = "foo", - ;; value = 270349836 - ;; }, { - ;; name = 0x12
, - ;; value = 0 - ;; }, { - ;; name = 0x0, - ;; value = 0 - ;; }} - ;; - (list (concat " *" - "\\(static \\)?" ; 1 - "\\([$a-zA-Z_][a-zA-Z0-9_:]*\\) = " ; 2 - "\\((" ; 3 - "\\(" ; .4 - "\\(signed \\|unsigned \\)?" ; ..5 - "\\(struct \\|class \\|union \\|enum \\)?"; ..6 - "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)" ; ..7 - "\\)" ; .4 - "[ *]*)" ; - "\\)?" ; 3 - "\\(" ; 8 - ".*" - " <\\([a-zA-Z_~][a-zA-Z0-9_:]*\\)" ; .9 - "\\+?[0-9]+?>" ; . - "\\)?" ; 8 - ) - '(nil ; 1 - gdb-variable-name-token ; 2 - nil ; 3 - gdb-type-name-token ; 4 - nil ; 5 - nil ; 6 - nil ; 7 - nil ; 8 - gdb-function-name-token ; 9 - )) - - ;; Purify output: - ;; UMR: Uninitialized memory read: - ;; * This is occurring while in: - ;; SHA1_Update [algsha.c:137] - ;; * Reading 1 byte from 0xefffdb34 on the stack. - (list (concat "[ \t]+" - "\\([a-zA-Z_~][a-zA-Z0-9_:]*\\)[ \t]*" ; 1 - "\\[\\(" ; 2 - "\\([^ \t\n:]+\\):" ; .3 - "\\([0-9]+\\)" ; .4 - "\\)\\]" ; 2 - ) - '(gdb-function-name-token ; 1 - gdb-function-location-token ; 2 (3+4) - )) - - ;; Purify output: - ;; * Address 0xefffdb34 is 36 bytes past start of local variable \ - ;; "data" in function fe_EventForRNG. - (list (concat ".*\\bAddress " - "\\(0x[0-9A-Fa-f]+\\) +" ; 1 - ".*\\bvariable \"" ; - "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)\"" ; 2 - "\\(" ; 3 - ".*\\bfunction " ; . - "\\([a-zA-Z_~][a-zA-Z0-9_:]*\\)" ; .4 - "\\)?" ; 3 - ) - '(nil ;gdb-address-token ; 1 - gdb-variable-name-token ; 2 - nil ; 3 - gdb-function-name-token ; 4 - )) - )) - "Patterns to highlight in gdb buffers. -Each element of this list takes the form - ( \"regexp\" ( token-1 token-2 ... )) -where token-N is the token to place on the text matched - by sub-pattern N in the match data. - -The patterns should not begin with \"^\".") - - -(defun gdb-highlight-line () - "Highlight any tokens on the line which match gdb-highlight-token-patterns." - (map-extents #'(lambda (e ignore) (delete-extent e)) - nil - (point) (save-excursion (forward-line 1) (point)) - nil nil 'gdb-token) - (while (looking-at comint-prompt-regexp) - (goto-char (match-end 0))) - (if (eobp) - nil - (let ((tokens gdb-highlight-token-patterns) - (do-magic-variable-hack nil)) - (while tokens - (if (not (looking-at (car (car tokens)))) - (setq tokens (cdr tokens)) - (let ((i 1) - (types (nth 1 (car tokens)))) - (if (eq (car types) 'gdb-variable-name-token) - (setq do-magic-variable-hack t)) - (while types - (cond ((not (and (car types) - (match-beginning i))) - nil) - ((memq (car types) '(gdb-arglist-token - gdb-arglist-types-token)) - (gdb-highlight-arglist (car types) - (match-beginning i) - (match-end i))) - ((/= ?$ (char-after (match-beginning i))) - (gdb-highlight-token (car types) - (match-beginning i) - (match-end i)))) - (setq i (1+ i) - types (cdr types))) - - (if (not do-magic-variable-hack) - ;; we're done. - (setq tokens nil) - ;; else, do a grody hack to cope with multiple variables - ;; on the same line. - (save-restriction - (let ((p (point)) - (ok nil)) - (end-of-line) - (narrow-to-region p (point)) - (goto-char (match-end 0)) - (if (= (following-char) ?\{) - (progn - (forward-char 1) - (setq ok t)) - (setq p (scan-sexps (point) 1 nil t)) - (setq ok (if (null p) - nil - (goto-char p) - (if (or (= (following-char) ?\,) - (= (following-char) ?\})) - t - (setq p (scan-sexps (point) 1 nil t)) - (if (null p) - nil - (goto-char p) - t))))) - (if ok - ;; skip over the comma and go around again. - (and (looking-at "}?[ \t]*,[ \t]*") - (goto-char (match-end 0))) - ;; saw something unexpected; give up on this line. - (setq tokens nil))))) - ))))) - nil) - -(defun gdb-highlight-token (type start end) - "Helper for gdb-highlight-line -- makes an extent for one matched token." - (let ((e (make-extent start end))) - (set-extent-property e 'gdb-token type) - (set-extent-property e 'highlight 't) - (set-extent-property e 'help-echo 'gdb-token-help-echo) - (set-extent-property e 'face (get type 'gdb-token-face)) - (set-extent-property e 'keymap (get type 'gdb-token-keymap)) - e)) - -(defun gdb-highlight-arglist (type start end) - "Helper for gdb-highlight-line. -Makes extents for variables or types in an arglist." - (save-match-data - (save-excursion - (goto-char end) - (if (eq (preceding-char) ?\)) - (setq end (1- end))) - (goto-char start) - (if (eq (following-char) ?\() - (forward-char 1)) - (set-extent-property (make-extent start end) 'gdb-token type) - - (cond - ((eq type 'gdb-arglist-token) - (let* ((pat1 "\\([a-zA-Z_][a-zA-Z0-9_:]*\\)=") - (pat2 ", \\([a-zA-Z_][a-zA-Z0-9_:]*\\)=") - (pat pat1)) - (while(re-search-forward pat end t) - (gdb-highlight-token 'gdb-variable-name-token - (match-beginning 1) (match-end 1)) - (cond ((looking-at - "0?x?[0-9A-Fa-f]+ <\\([a-zA-Z_~][a-zA-Z0-9_:]*\\)>") - (goto-char (match-end 0)) - (gdb-highlight-token 'gdb-function-name-token - (match-beginning 1) (match-end 1)))) - (setq pat pat2)))) - - ((eq type 'gdb-arglist-types-token) - (let ((pat (eval-when-compile - (concat - "\\(" ; 1 - "\\(signed \\|unsigned \\)?" ; .2 - "\\(struct \\|class \\|union \\|enum \\)?" ; .3 - "\\(?\\)" ; .4 - "\\)" ; 1 - "[ *]*" - "\\((\\*) *(.*)\\)?" ; 5 - )))) - (while (< (point) end) - (cond ((looking-at pat) - (goto-char (match-end 0)) - (gdb-highlight-token 'gdb-type-name-token - (match-beginning 1) (match-end 1)) - (if (looking-at " *, *") - (goto-char (match-end 0)))) - (t - ;; error -- try to cope... - (search-forward "," (1+ end) t)))))) - (t - (error "unknown arglist type %s" type))))) - nil) - -(defun gdb-token-help-echo (extent) - "Used as the 'mouse-help property of gdb-token extents, -to describe the binding on button2." - (let* ((map (extent-property extent 'keymap)) - (key 'button2) - (fn (and map (lookup-key map key))) - (doc (and fn (symbolp fn) - (if (fboundp fn) - (format "%s: %s" key (documentation fn)) - (format "Error: %s is undefined" fn))))) - (if doc - (save-match-data - (if (string-match "\n" doc) - (setq doc (substring doc 0 (match-beginning 0)))))) - (or doc - (concat "Error: no doc for " - (symbol-name (extent-property extent 'gdb-token)))))) - -(defun gdb-get-line-token-extents (tokens) - "Given a list of gdb-tokens, returns this line's extents of those types. -The returned value is a list of the same length as the `tokens' list, with -the corresponding extents in the corresponding positions. If an extent -isn't found, nil is placed in the result-list instead." - (setq tokens (append tokens nil)) - (let* ((result (make-list (length tokens) nil))) - (save-excursion - (beginning-of-line) - (map-extents #'(lambda (e ignore) - (let ((type (extent-property e 'gdb-token)) - (r1 tokens) - (r2 result)) - (while r1 - (cond ((and (car r1) (eq type (car r1))) - (setcar r1 nil) - (setcar r2 e) - (setq r1 nil))) - (setq r1 (cdr r1) - r2 (cdr r2)))) - nil) - nil - (point) - (progn (forward-line 1) (point)) - nil nil - 'gdb-token) - result))) - - -;;; Remembering directory names. -;;; gdb and gdb-mode conspire to hide from us the full file names of things -;;; that are presented into the buffer; this is an attempt to circumvent that. - -(defvar gdb-highlight-last-directory nil) -(defvar gdb-highlight-last-directory-table nil) - -(defun gdb-highlight-remember-directory () - ;; When gdb deigns to give us a full pathname, and it's in a different - ;; directory than last time, cache it away on one of the nearby gdb-token - ;; extents. (We intern it to avoid hanging on to a lot of strings.) - (cond ((and (boundp 'gdb-last-frame) - (car gdb-last-frame)) - (cond ((not gdb-highlight-last-directory-table) - (set (make-local-variable 'gdb-highlight-last-directory) nil) - (set (make-local-variable 'gdb-highlight-last-directory-table) - (make-vector 211 0)))) - (let ((dir (file-name-directory (car gdb-last-frame)))) - (setq dir (intern dir gdb-highlight-last-directory-table)) - (cond ((not (eq dir gdb-highlight-last-directory)) - (let ((extent (previous-extent (current-buffer)))) - (setq gdb-highlight-last-directory dir) - (while extent - (cond ((extent-property extent 'gdb-token) - (set-extent-property extent 'gdb-directory dir) - (setq extent nil)) - (t - (setq extent (previous-extent extent)))))))))))) - -(defun gdb-guess-directory () - "Guess what directory gdb was talking about when it wrote the current line." - (let ((extent (or (map-extents #'(lambda (e ignore) e) - (current-buffer) (point) (point-max)) - (previous-extent (current-buffer)) - (error "no extents"))) - (dir nil)) - (while extent - (setq dir (extent-property extent 'gdb-directory)) - (if dir - (setq extent nil) - (setq extent (previous-extent extent)))) - (if dir - (symbol-name dir) - default-directory))) - -(defun gdb-guess-file-name (file) - "Given a directoryless file name printed by gdb, find the file. -First it tries to expand the file relative to `gdb-guess-directory', -and if the resultant file doesn't exist, it tries every other directory -gdb has ever told us about, in no particular order." - (abbreviate-file-name - (if (file-name-absolute-p file) - file - (let ((file2 (expand-file-name file (gdb-guess-directory)))) - (if (file-exists-p file2) - file2 - ;; Oh boy, gdb didn't tell us what directory it's in. - ;; A-hunting we will go. - (if (catch 'done - (mapatoms #'(lambda (dir) - (setq file2 (expand-file-name file - (symbol-name dir))) - (if (file-exists-p file2) - (throw 'done t))) - gdb-highlight-last-directory-table) - nil) - file2 - (expand-file-name file))))))) - - -;;; Commands which are invoked from bindings in the keymaps of the tokens. - -(defun gdb-mouse-toggle-breakpoint-enabled (event &optional what) - "Toggle whether the breakpoint is enabled. -Looks for a gdb-breakpoint extent on the line under the mouse, -and executes an `enable' or `disable' command as appropriate. -Optional arg `what' may be 'enable, 'disable, or 'toggle (default.)" - (interactive "@*e") - (let (number target enabled-p) - (save-excursion - (mouse-set-point event) - (let* ((extents (gdb-get-line-token-extents - '(gdb-breakpoint-number-token - gdb-info-breakpoint-number-token - gdb-enabled-token))) - (be (or (nth 0 extents) (nth 1 extents))) - (ee (nth 2 extents))) - - (or be - (error "no breakpoint-number extent on this line")) - (setq number - (buffer-substring (extent-start-position be) - (extent-end-position be))) - (if (string-match " [0-9]+\\'" number) - (setq number (substring number (1+ (match-beginning 0))))) - (setq number (string-to-int number)) - (or (> number 0) - (error "couldn't find breakpoint number")) - (if (null ee) - (setq enabled-p 'unknown) - (setq target (extent-start-position ee)) - (goto-char target) - (setq enabled-p - (cond ((looking-at "[yY]\\b") t) - ((looking-at "[nN]\\b") nil) - (t (error "enabled is not y or n?"))))) - - (cond ((eq what 'enable) - (setq enabled-p nil)) - ((eq what 'disable) - (setq enabled-p t)) - ((or (eq what 'toggle) (null what)) - (if (eq enabled-p 'unknown) - (error - "can't toggle breakpoint: don't know current state"))) - (t - (error "what must be enable, disable, toggle, or nil."))) - )) - - (gdb-menu-command (format "%s %d" - (if enabled-p "disable" "enable") - number) - nil) - (message "%s breakpoint %d." - (if enabled-p "Disabled" "Enabled") - number) - (cond (target - (save-excursion - (goto-char target) - (insert (if enabled-p "n" "y")) - (delete-char 1) - ;; don't let shell-fonts or font-lock second-guess us. - (remove-text-properties (1- (point)) (point) '(face)))))) - nil) - -(defun gdb-mouse-enable-breakpoint (event) - "Enable the breakpoint. -Looks for a gdb-breakpoint extent on the line under the mouse, -and executes an `enable' command" - (interactive "@*e") - (gdb-mouse-toggle-breakpoint-enabled event 'enable)) - -(defun gdb-mouse-disable-breakpoint (event) - "Disable the breakpoint. -Looks for a gdb-breakpoint extent on the line under the mouse, -and executes a `disable' command" - (interactive "@*e") - (gdb-mouse-toggle-breakpoint-enabled event 'disable)) - - -;; compatibility hack... -(or (fboundp 'extent-object) (fset 'extent-object 'extent-buffer)) - -(defun gdb-mouse-edit-function (event) - "Edit the definition of this function (as with \\[find-tag]) -Looks for a gdb-function-name extent on the line under the mouse, -and runs find-tag on the text under that extent." - (interactive "@*e") - (let (extent) - (save-excursion - (mouse-set-point event) - (setq extent (or (car (gdb-get-line-token-extents - '(gdb-function-name-token))) - (error "no function-name extent on this line")))) - (find-tag - (buffer-substring (extent-start-position extent) - (extent-end-position extent) - (extent-object extent))))) - - -(defun gdb-mouse-edit-function-location (event) - "Edit the source file of this function. -Looks for a gdb-function-location extent on line of the mouse, -and parses the text under it." - (interactive "@*e") - (let (file line) - (save-excursion - (mouse-set-point event) - (let ((extent (or (car (gdb-get-line-token-extents - '(gdb-function-location-token))) - (error "no function-location extent on this line")))) - (goto-char (extent-start-position extent)) - (or (looking-at "\\([^ \t\n:,]+\\):\\([0-9]+\\)") - (looking-at "\\([^ \t\n:,]+\\),? line \\([0-9]+\\)") - (error "no file position on this line")) - (setq file (buffer-substring (match-beginning 1) (match-end 1)) - line (buffer-substring (match-beginning 2) (match-end 2))) - (setq file (gdb-guess-file-name file) - line (string-to-int line)) - )) - (if (file-exists-p file) - (find-file-other-window file) - (signal 'file-error (list "File not found" file))) - (goto-line line))) - - -(defun gdb-mouse-goto-frame (event) - "Select this stack frame. -Looks for a gdb-frame-number extent on the line of the mouse, -and executes a `frame' command to select that frame." - (interactive "@*e") - (let (number) - (save-excursion - (mouse-set-point event) - (let ((extent (or (car (gdb-get-line-token-extents - '(gdb-frame-number-token))) - (error "no frame-number extent on this line")))) - (goto-char (extent-start-position extent)) - (if (eq (following-char) ?#) - (forward-char 1)) - (setq number (string-to-int - (buffer-substring (point) - (extent-end-position extent)))))) - (gdb-menu-command (format "frame %d" number) t)) - nil) - - -(defun gdb-mouse-get-variable-reference (event) - "Returns a string which references the variable under the mouse. -This works even if the variable is deep inside nested arrays or structures. -If the variable seems to hold a pointer, then a \"*\" will be prepended." - (save-excursion - (let* ((extent (if (extentp event) - event - (progn - (mouse-set-point event) - (extent-at (point) nil 'gdb-token)))) - dereference-p - name) - (or (and extent - (eq (extent-property extent 'gdb-token) - 'gdb-variable-name-token)) - (error "not over a variable name")) - (setq name (buffer-substring (extent-start-position extent) - (extent-end-position extent))) - (save-excursion - (goto-char (extent-end-position extent)) - (if (and (looking-at " *= *\\(([^)]+)\\)? *0x[0-9a-fA-F]+") ; pointer - (progn - (goto-char (match-end 0)) - (not (looking-at " +\"")))) ; but not string - (setq dereference-p t)) - - ;; Now, if this variable is buried in a structure, compose a complete - ;; reference-chain to it. - (goto-char (extent-start-position extent)) - - (let ((done nil)) - (while (not done) - (skip-chars-backward " \t") - (if (or (and (/= (preceding-char) ?\n) - (/= (preceding-char) ?\,) - (/= (preceding-char) ?\{)) - (<= (buffer-syntactic-context-depth) 0)) - (setq done t) - (let ((p (scan-lists (point) -1 1))) - (if (null p) - (setq done t) - (goto-char (setq p (- p 3))) - (cond - ((looking-at " = {") - (skip-chars-backward "a-zA-Z0-9_") - (if (= (preceding-char) ?\$) - (forward-char -1)) - (setq name (concat (buffer-substring (point) p) "." name))) - - ((looking-at "}, +{") - (forward-char 1) - (let ((parse-sexp-ignore-comments nil) - (count 0)) - (while (setq p (scan-sexps (point) -1 nil t)) - (goto-char p) - (setq count (1+ count))) - - (setq name (format "[%d].%s" count name)) - - ;; up out of the list - (skip-chars-backward " \t\n") - (if (= (preceding-char) ?\{) - (forward-char -1)) - - ;; we might be tightly nested in slot 0... - (while (= (preceding-char) ?\{) - (forward-char -1) - (setq name (concat "[0]" name))) - - (skip-chars-backward " \t") - (if (= (preceding-char) ?=) (forward-char -1)) - (skip-chars-backward " \t") - (setq p (point)) - (skip-chars-backward "a-zA-Z0-9_") - (if (= (preceding-char) ?\$) - (forward-char -1)) - - (setq name (concat (buffer-substring (point) p) name)) - )) - (t - (setq done t))))))))) - - (if dereference-p - (setq name (concat "*" name))) - name))) - -(defun gdb-mouse-print-variable (event) - "Print the value of this variable. -Finds a variable under the mouse, and figures out whether it is inside of -a structure, and composes and executes a `print' command. If the variable -seems to hold a pointer, prints the object pointed to." - (interactive "@*e") - (gdb-menu-command (concat "print " - (gdb-mouse-get-variable-reference event)) - t)) - -(defun gdb-mouse-print-variable-type (event) - "Describe the type of this variable. -Finds a variable under the mouse, and figures out whether it is inside of -a structure, and composes and executes a `whatis' command. If the variable -seems to hold a pointer, describes the type of the object pointed to." - (interactive "@*e") - (gdb-menu-command (concat "whatis " - (gdb-mouse-get-variable-reference event)) - t)) - -(defun gdb-mouse-print-type (event) - "Describe this type. -Finds a type description under the mouse, and executes a `ptype' command." - (interactive "@*e") - (let* ((extent (save-excursion - (mouse-set-point event) - (extent-at (point) nil 'gdb-token))) - name) - (or (and extent - (eq (extent-property extent 'gdb-token) 'gdb-type-name-token)) - (error "not over a type name")) - (setq name (buffer-substring (extent-start-position extent) - (extent-end-position extent))) - (gdb-menu-command (format "ptype %s" name) - t)) - nil) - - -;;; Popup menus - -(defun gdb-menu-command (command &optional scroll-to-bottom) - "Sends the command to gdb. -If gdb is not sitting at a prompt, interrupts it first -\(as if with \\[gdb-control-c-subjob]), executes the command, and then lets -the debugged program continue. - -If scroll-to-bottom is true, then point will be moved to after the new -output. Otherwise, an effort is made to avoid scrolling the window and -to keep point where it was." - - ;; this is kinda like gdb-call except for the interrupt-first behavior, - ;; but also it leaves the commands in the buffer instead of trying to - ;; hide them. - - (let* ((proc (or (get-buffer-process (current-buffer)) - (error "no process in %s" (buffer-name (current-buffer))))) - (window (selected-window)) - wstart - (opoint (point)) - was-at-bottom - running-p) - - (if (not (eq (current-buffer) (window-buffer window))) - (setq window (get-buffer-window (current-buffer)))) - (setq wstart (window-start window)) - - (let ((pmark (process-mark proc))) - (setq was-at-bottom (>= (point) pmark)) - (goto-char pmark) - (delete-region (point) (point-max))) - - (setq running-p (bolp)) ; maybe not the best way to tell... - - (cond (running-p - (message "Program is running -- interrupting first...") - (gdb-control-c-subjob) - (while (accept-process-output proc 1) - ;; continue accepting output as long as it's arriving - ))) - - (message "%s" command) - (goto-char (process-mark proc)) - (insert command) - (comint-send-input) - - ;; wait for the command to be accepted - (accept-process-output proc) - (goto-char (process-mark proc)) - - ;; continue, if we had interrupted - (cond (running-p - (insert "continue") - (comint-send-input))) - - (if scroll-to-bottom - (goto-char (process-mark proc)) - - (set-window-start window wstart) - (goto-char opoint) - (if was-at-bottom - (if (pos-visible-in-window-p (process-mark proc) window) - (goto-char (process-mark proc)) - (goto-char (window-end window)) - (forward-line -2)))) - ) - nil) - - -(defun gdb-make-context-menu (event) - "Returns a menu-desc corresponding to the stack-frame line under the mouse. -Returns nil if not over a stack-frame." - (save-excursion - (mouse-set-point event) - (let* ((extents (gdb-get-line-token-extents - '(gdb-breakpoint-number-token - gdb-info-breakpoint-number-token - gdb-enabled-token - gdb-frame-number-token - gdb-function-name-token - gdb-function-location-token - gdb-arglist-token - gdb-arglist-types-token - gdb-variable-name-token - gdb-type-name-token - ))) - (bnumber (or (nth 0 extents) - (nth 1 extents))) - (enabled-p (nth 2 extents)) - (fnumber (nth 3 extents)) - (name (nth 4 extents)) - (loc (nth 5 extents)) - (al (nth 6 extents)) - (alt (nth 7 extents)) - (var (nth 8 extents)) - (type (nth 9 extents)) - (var-e var)) - - ;; If this line has an arglist, only document variables and types - ;; if the mouse is directly over them. - (if (or al alt) - (setq var nil - type nil)) - - ;; Always prefer the object under the mouse to one elsewhere on the line. - (let* ((e (extent-at (point) nil 'gdb-token)) - (p (and e (extent-property e 'gdb-token)))) - (cond ((eq p 'gdb-function-name-token) (setq name e)) - ((eq p 'gdb-variable-name-token) (setq var e var-e e)) - ((eq p 'gdb-type-name-token) (setq type e)) - )) - - ;; Extract the frame number (it may begin with "#".) - (cond (fnumber - (goto-char (extent-start-position fnumber)) - (if (eq (following-char) ?#) - (forward-char 1)) - (setq fnumber - (string-to-int - (buffer-substring (point) - (extent-end-position fnumber)))))) - - ;; Extract the breakpoint number (it may begin with "Breakpoint ".) - (cond (bnumber - (setq bnumber - (buffer-substring (extent-start-position bnumber) - (extent-end-position bnumber))) - (if (string-match " [0-9]+\\'" bnumber) - (setq bnumber (substring bnumber (1+ (match-beginning 0))))) - (setq bnumber (string-to-int bnumber)) - (or (> bnumber 0) - (error "couldn't parse breakpoint number")))) - - (cond ((null enabled-p) - (setq enabled-p 'unknown)) - ((memq (char-after (extent-start-position enabled-p)) '(?y ?Y)) - (setq enabled-p 't)) - ((memq (char-after (extent-start-position enabled-p)) '(?n ?N)) - (setq enabled-p 'nil)) - (t - (setq enabled-p 'unknown))) - - ;; Convert the extents to strings. - ;; - (if name - (setq name (buffer-substring (extent-start-position name) - (extent-end-position name)))) - (if loc - (setq loc (buffer-substring (extent-start-position loc) - (extent-end-position loc)))) - (if var - (setq var (buffer-substring (extent-start-position var) - (extent-end-position var)))) - (if type - (setq type (buffer-substring (extent-start-position type) - (extent-end-position type)))) - - ;; Return a menu description list. - ;; - (nconc - (if (and bnumber (not (eq enabled-p 'nil))) - (list (vector (format "Disable Breakpoint %d" - bnumber) - (list 'gdb-mouse-disable-breakpoint event) - t))) - (if (and bnumber (not (eq enabled-p 't))) - (list (vector (format "Enable Breakpoint %d" - bnumber) - (list 'gdb-mouse-enable-breakpoint event) - t))) - (if bnumber - (list (vector (format "Delete Breakpoint %d" bnumber) - (list 'gdb-menu-command (format "delete %d" bnumber) - nil) - t))) - (if var - (list (vector (format "Print Value of `%s'" var) - (list 'gdb-mouse-print-variable var-e) - t) - (vector (format "Print Type of `%s'" var) - (list 'gdb-mouse-print-variable-type var-e) - t))) - (if name - (list (vector (format "Edit Definition of `%s'" name) - (list 'gdb-mouse-edit-function event) - t) - (vector (format "Set Breakpoint on `%s'" name) - (list 'gdb-menu-command (format "break %s" name) nil) - t))) - (if loc - (list (vector (format "Visit Source Line (%s)" loc) - (list 'gdb-mouse-edit-function-location event) - t))) - (if type - (list (vector (format "Describe Type `%s'" type) - (list 'gdb-menu-command (format "ptype %s" type) t) - t))) - (if fnumber - (list (vector (format "Select Stack Frame %d" fnumber) - (list 'gdb-menu-command (format "frame %d" fnumber) t) - t))) - )))) - - -(defun gdb-popup-menu (event) - "Pop up a context-sensitive menu of gdb-mode commands." - (interactive "_@e") - (select-window (event-window event)) - (let (menu) - (save-excursion - (setq menu (append (if (boundp 'gdb-popup-menu) - (append (cdr gdb-popup-menu) - '("---"))) - (if (boundp 'comint-popup-menu) - (cdr comint-popup-menu)))) - (let ((history (if (fboundp 'comint-make-history-menu) - (comint-make-history-menu))) - (context (gdb-make-context-menu event))) - (if history - (setq menu - (append menu (list "---" (cons "Command History" history))))) - (if context - (setq menu (append context (cons "---" menu)))) - ) - (setq menu (cons (if (boundp 'gdb-popup-menu) - (car gdb-popup-menu) - "GDB Commands") - menu))) - (popup-menu menu event))) - - -;;; Patch it in... - -(or (fboundp 'gdb-highlight-orig-filter) - (fset 'gdb-highlight-orig-filter (symbol-function 'gdb-filter))) - -(defun gdb-highlight-filter (proc string) - (let ((p (marker-position (process-mark proc)))) - (prog1 - (gdb-highlight-orig-filter proc string) - - (save-match-data - ;; - ;; If there are no newlines in this string at all, then don't - ;; bother processing it -- we will pick up these characters on - ;; the next time around, when the line's newline gets inserted. - ;; - (cond - ((string-match "\n" string) - (save-excursion - (set-buffer (process-buffer proc)) - (goto-char p) - (let ((p2 (marker-position (process-mark proc))) - p3) - ;; - ;; If gdb has given us a full pathname, remember it. (Do this - ;; before emitting any gdb-token extents, so that we attach it - ;; to the buffer *before* any of the extents to which it is - ;; known to correspond. - ;; - (gdb-highlight-remember-directory) - ;; - ;; Now highlight each line that has been written. If we wrote - ;; the last half of a line, re-highlight that whole line. (We - ;; need to do that so that the regexps will match properly; - ;; the "\n" test above also depends on this behavior.) - ;; - ;; But don't highlight lines longer than 5000 characters -- that - ;; probably means something is spewing, and we'll just get stuck - ;; hard in the regexp matcher. - ;; - (beginning-of-line) - (while (< (point) p2) - (goto-char (prog1 - (point) - (forward-line 1) - (setq p3 (point)))) - (if (< (- p3 (point)) 5000) - (gdb-highlight-line)) - (goto-char p3)))))))))) - -(fset 'gdb-filter 'gdb-highlight-filter) - - -(provide 'gdb-highlight) - -;;; gdb-highlight.el ends here - ---------------4273DDB4BB90CEC3B645B5AC-- - - diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/gdb.el --- a/lisp/comint/gdb.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,700 +0,0 @@ -;;; gdb.el --- run gdb under Emacs - -;; Author: W. Schelter, University of Texas -;; wfs@rascal.ics.utexas.edu -;; Rewritten by rms. -;; Keywords: c, unix, tools, debugging - -;; Some ideas are due to Masanobu. - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; Description of GDB interface: - -;; A facility is provided for the simultaneous display of the source code -;; in one window, while using gdb to step through a function in the -;; other. A small arrow in the source window, indicates the current -;; line. - -;; Starting up: - -;; In order to use this facility, invoke the command GDB to obtain a -;; shell window with the appropriate command bindings. You will be asked -;; for the name of a file to run. Gdb will be invoked on this file, in a -;; window named *gdb-foo* if the file is foo. - -;; M-s steps by one line, and redisplays the source file and line. - -;; You may easily create additional commands and bindings to interact -;; with the display. For example to put the gdb command next on \M-n -;; (def-gdb next "\M-n") - -;; This causes the emacs command gdb-next to be defined, and runs -;; gdb-display-frame after the command. - -;; gdb-display-frame is the basic display function. It tries to display -;; in the other window, the file and line corresponding to the current -;; position in the gdb window. For example after a gdb-step, it would -;; display the line corresponding to the position for the last step. Or -;; if you have done a backtrace in the gdb buffer, and move the cursor -;; into one of the frames, it would display the position corresponding to -;; that frame. - -;; gdb-display-frame is invoked automatically when a filename-and-line-number -;; appears in the output. - -;;; Code: - -(require 'comint) -(require 'shell) - -(condition-case nil - (if (featurep 'toolbar) - (require 'eos-toolbar "sun-eos-toolbar")) - (error nil)) - -(defvar gdb-last-frame) -(defvar gdb-delete-prompt-marker) -(defvar gdb-filter-accumulator) -(defvar gdb-last-frame-displayed-p) -(defvar gdb-arrow-extent nil) -(or (fboundp 'make-glyph) (fset 'make-glyph 'identity)) ; work w/ pre beta v12 -(defvar gdb-arrow-glyph (make-glyph "=>")) - -(make-face 'gdb-arrow-face) -(or (face-differs-from-default-p 'gdb-arrow-face) - ;; Usually has a better default value than highlight does - (copy-face 'isearch 'gdb-arrow-face)) - -;; Hooks can side-effect extent arg to change extent properties -(defvar gdb-arrow-extent-hooks '()) - -(defvar gdb-prompt-pattern "^>\\|^(.*gdb[+]?) *\\|^---Type to.*--- *" - "A regexp to recognize the prompt for gdb or gdb+.") - -(defvar gdb-mode-map nil - "Keymap for gdb-mode.") - -(defvar gdb-toolbar - '([eos::toolbar-stop-at-icon - gdb-toolbar-break - t - "Stop at selected position"] - [eos::toolbar-stop-in-icon - gdb-toolbar-break - t - "Stop in function whose name is selected"] - [eos::toolbar-clear-at-icon - gdb-toolbar-clear - t - "Clear at selected position"] - [eos::toolbar-evaluate-icon - nil - nil - "Evaluate selected expression; shows in separate XEmacs frame"] - [eos::toolbar-evaluate-star-icon - nil - nil - "Evaluate selected expression as a pointer; shows in separate XEmacs frame"] - [eos::toolbar-run-icon - gdb-run - t - "Run current program"] - [eos::toolbar-cont-icon - gdb-cont - t - "Continue current program"] - [eos::toolbar-step-into-icon - gdb-step - t - "Step into (aka step)"] - [eos::toolbar-step-over-icon - gdb-next - t - "Step over (aka next)"] - [eos::toolbar-up-icon - gdb-up - t - "Stack Up (towards \"cooler\" - less recently visited - frames)"] - [eos::toolbar-down-icon - gdb-down - t - "Stack Down (towards \"warmer\" - more recently visited - frames)"] - [eos::toolbar-fix-icon nil nil "Fix (not available with gdb)"] - [eos::toolbar-build-icon - toolbar-compile - t - "Build (aka make -NYI)"] - )) - -(if gdb-mode-map - nil - (setq gdb-mode-map (make-sparse-keymap)) - (set-keymap-name gdb-mode-map 'gdb-mode-map) - (set-keymap-parents gdb-mode-map (list comint-mode-map)) - (define-key gdb-mode-map "\C-l" 'gdb-refresh) - (define-key gdb-mode-map "\C-c\C-c" 'gdb-control-c-subjob) - (define-key gdb-mode-map "\t" 'comint-dynamic-complete) - (define-key gdb-mode-map "\M-?" 'comint-dynamic-list-completions)) - -(define-key ctl-x-map " " 'gdb-break) -(define-key ctl-x-map "&" 'send-gdb-command) - -;;Of course you may use `def-gdb' with any other gdb command, including -;;user defined ones. - -(defmacro def-gdb (name key &optional doc &rest forms) - (let* ((fun (intern (format "gdb-%s" name))) - (cstr (list 'if '(not (= 1 arg)) - (list 'format "%s %s" name 'arg) - name))) - (list 'progn - (nconc (list 'defun fun '(arg) - (or doc "") - '(interactive "p") - (list 'gdb-call cstr)) - forms) - (and key (list 'define-key 'gdb-mode-map key (list 'quote fun)))))) - -(def-gdb "step" "\M-s" "Step one source line with display" - (gdb-delete-arrow-extent)) -(def-gdb "stepi" "\M-i" "Step one instruction with display" - (gdb-delete-arrow-extent)) -(def-gdb "finish" "\C-c\C-f" "Finish executing current function" - (gdb-delete-arrow-extent)) -(def-gdb "run" nil "Run the current program" - (gdb-delete-arrow-extent)) - -;;"next" and "cont" were bound to M-n and M-c in Emacs 18, but these are -;;poor choices, since M-n is used for history navigation and M-c is -;;capitalize-word. These are defined without key bindings so that users -;;may choose their own bindings. -(def-gdb "next" "\C-c\C-n" "Step one source line (skip functions)" - (gdb-delete-arrow-extent)) -(def-gdb "cont" "\C-c\M-c" "Proceed with the program" - (gdb-delete-arrow-extent)) - -(def-gdb "up" "\C-c<" "Go up N stack frames (numeric arg) with display") -(def-gdb "down" "\C-c>" "Go down N stack frames (numeric arg) with display") - -(defvar gdb-display-mode nil - "Minor mode for gdb frame display") -(or (assq 'gdb-display-mode minor-mode-alist) - (setq minor-mode-alist - (purecopy - (append minor-mode-alist - '((gdb-display-mode " Frame")))))) - -(defun gdb-display-mode (&optional arg) - "Toggle GDB Frame display mode -With arg, turn display mode on if and only if arg is positive. -In the display minor mode, source file are displayed in another -window for repective \\[gdb-display-frame] commands." - (interactive "P") - (setq gdb-display-mode (if (null arg) - (not gdb-display-mode) - (> (prefix-numeric-value arg) 0)))) - -;; Using cc-mode's syntax table is broken. -(defvar gdb-mode-syntax-table nil - "Syntax table for GDB mode.") - -;; This is adapted from CC Mode 5.11. -(unless gdb-mode-syntax-table - (setq gdb-mode-syntax-table (make-syntax-table)) - ;; DO NOT TRY TO SET _ (UNDERSCORE) TO WORD CLASS! - (modify-syntax-entry ?_ "_" gdb-mode-syntax-table) - (modify-syntax-entry ?\\ "\\" gdb-mode-syntax-table) - (modify-syntax-entry ?+ "." gdb-mode-syntax-table) - (modify-syntax-entry ?- "." gdb-mode-syntax-table) - (modify-syntax-entry ?= "." gdb-mode-syntax-table) - (modify-syntax-entry ?% "." gdb-mode-syntax-table) - (modify-syntax-entry ?< "." gdb-mode-syntax-table) - (modify-syntax-entry ?> "." gdb-mode-syntax-table) - (modify-syntax-entry ?& "." gdb-mode-syntax-table) - (modify-syntax-entry ?| "." gdb-mode-syntax-table) - (modify-syntax-entry ?\' "\"" gdb-mode-syntax-table) - ;; add extra comment syntax - (modify-syntax-entry ?/ ". 14" gdb-mode-syntax-table) - (modify-syntax-entry ?* ". 23" gdb-mode-syntax-table)) - - -(defun gdb-mode () - "Major mode for interacting with an inferior Gdb process. -The following commands are available: - -\\{gdb-mode-map} - -\\[gdb-display-frame] displays in the other window -the last line referred to in the gdb buffer. See also -\\[gdb-display-mode]. - -\\[gdb-step],\\[gdb-next], and \\[gdb-nexti] in the gdb window, -call gdb to step,next or nexti and then update the other window -with the current file and position. - -If you are in a source file, you may select a point to break -at, by doing \\[gdb-break]. - -Commands: -Many commands are inherited from comint mode. -Additionally we have: - -\\[gdb-display-frame] display frames file in other window -\\[gdb-step] advance one line in program -\\[send-gdb-command] used for special printing of an arg at the current point. -C-x SPACE sets break point at current line." - (interactive) - (comint-mode) - (use-local-map gdb-mode-map) - (set-syntax-table gdb-mode-syntax-table) - (make-local-variable 'gdb-last-frame-displayed-p) - (make-local-variable 'gdb-last-frame) - (make-local-variable 'gdb-delete-prompt-marker) - (make-local-variable 'gdb-display-mode) - (make-local-variable' gdb-filter-accumulator) - (setq gdb-last-frame nil - gdb-delete-prompt-marker nil - gdb-filter-accumulator nil - gdb-display-mode t - major-mode 'gdb-mode - mode-name "Inferior GDB" - comint-prompt-regexp gdb-prompt-pattern - gdb-last-frame-displayed-p t) - (set (make-local-variable 'shell-dirtrackp) t) - ;;(make-local-variable 'gdb-arrow-extent) - (and (extentp gdb-arrow-extent) - (delete-extent gdb-arrow-extent)) - (setq gdb-arrow-extent nil) - ;; XEmacs change: - (make-local-hook 'kill-buffer-hook) - (add-hook 'kill-buffer-hook 'gdb-delete-arrow-extent nil t) - (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t) - (run-hooks 'gdb-mode-hook)) - -(defun gdb-delete-arrow-extent () - (let ((inhibit-quit t)) - (if gdb-arrow-extent - (delete-extent gdb-arrow-extent)) - (setq gdb-arrow-extent nil))) - -(defvar current-gdb-buffer nil) - -;;;###autoload -(defvar gdb-command-name "gdb" - "Pathname for executing gdb.") - -;;;###autoload -(defun gdb (path &optional corefile) - "Run gdb on program FILE in buffer *gdb-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for GDB. If you wish to change this, use -the GDB commands `cd DIR' and `directory'." - (interactive "FRun gdb on file: ") - (setq path (file-truename (expand-file-name path))) - (let ((file (file-name-nondirectory path))) - (switch-to-buffer (concat "*gdb-" file "*")) - (setq default-directory (file-name-directory path)) - (or (bolp) (newline)) - (insert "Current directory is " default-directory "\n") - (apply 'make-comint - (concat "gdb-" file) - (substitute-in-file-name gdb-command-name) - nil - "-fullname" - "-cd" default-directory - file - (and corefile (list corefile))) - (set-process-filter (get-buffer-process (current-buffer)) 'gdb-filter) - (set-process-sentinel (get-buffer-process (current-buffer)) 'gdb-sentinel) - ;; XEmacs change: turn on gdb mode after setting up the proc filters - ;; for the benefit of shell-font.el - (gdb-mode) - (gdb-set-buffer))) - -;;;###autoload -(defun gdb-with-core (file corefile) - "Debug a program using a corefile." - (interactive "fProgram to debug: \nfCore file to use: ") - (gdb file corefile)) - -(defun gdb-set-buffer () - (cond ((eq major-mode 'gdb-mode) - (setq current-gdb-buffer (current-buffer)) - (if (featurep 'eos-toolbar) - (set-specifier default-toolbar (cons (current-buffer) - gdb-toolbar)))))) - - -;; This function is responsible for inserting output from GDB -;; into the buffer. -;; Aside from inserting the text, it notices and deletes -;; each filename-and-line-number; -;; that GDB prints to identify the selected frame. -;; It records the filename and line number, and maybe displays that file. -(defun gdb-filter (proc string) - (let ((inhibit-quit t)) - (save-current-buffer - (set-buffer (process-buffer proc)) - (if gdb-filter-accumulator - (gdb-filter-accumulate-marker - proc (concat gdb-filter-accumulator string)) - (gdb-filter-scan-input proc string))))) - -(defun gdb-filter-accumulate-marker (proc string) - (setq gdb-filter-accumulator nil) - (if (> (length string) 1) - (if (= (aref string 1) ?\032) - (let ((end (string-match "\n" string))) - (if end - (progn - (let* ((first-colon (string-match ":" string 2)) - (second-colon - (string-match ":" string (1+ first-colon)))) - (setq gdb-last-frame - (cons (substring string 2 first-colon) - (string-to-int - (substring string (1+ first-colon) - second-colon))))) - (setq gdb-last-frame-displayed-p nil) - (gdb-filter-scan-input proc - (substring string (1+ end)))) - (setq gdb-filter-accumulator string))) - (gdb-filter-insert proc "\032") - (gdb-filter-scan-input proc (substring string 1))) - (setq gdb-filter-accumulator string))) - -(defun gdb-filter-scan-input (proc string) - (if (equal string "") - (setq gdb-filter-accumulator nil) - (let ((start (string-match "\032" string))) - (if start - (progn (gdb-filter-insert proc (substring string 0 start)) - (gdb-filter-accumulate-marker proc - (substring string start))) - (gdb-filter-insert proc string))))) - -(defun gdb-filter-insert (proc string) - (let ((moving (= (point) (process-mark proc))) - (output-after-point (< (point) (process-mark proc)))) - (save-excursion - ;; Insert the text, moving the process-marker. - (goto-char (process-mark proc)) - (insert-before-markers string) - (set-marker (process-mark proc) (point)) - (gdb-maybe-delete-prompt) - ;; Check for a filename-and-line number. - (gdb-display-frame - ;; Don't display the specified file - ;; unless (1) point is at or after the position where output appears - ;; and (2) this buffer is on the screen. - (or output-after-point - (not (get-buffer-window (current-buffer)))) - ;; Display a file only when a new filename-and-line-number appears. - t)) - (if moving (goto-char (process-mark proc)))) - - (let (s) - (if (and (should-use-dialog-box-p) - (setq s (or (string-match " (y or n) *\\'" string) - (string-match " (yes or no) *\\'" string)))) - (gdb-mouse-prompt-hack (substring string 0 s) (current-buffer)))) - ) - -(defun gdb-mouse-prompt-hack (prompt buffer) - (popup-dialog-box - (list prompt - (vector "Yes" (list 'gdb-mouse-prompt-hack-answer 't buffer) t) - (vector "No" (list 'gdb-mouse-prompt-hack-answer 'nil buffer) t) - nil - (vector "Cancel" (list 'gdb-mouse-prompt-hack-answer 'nil buffer) t) - ))) - -(defun gdb-mouse-prompt-hack-answer (answer buffer) - (let ((b (current-buffer))) - (unwind-protect - (progn - (set-buffer buffer) - (goto-char (process-mark (get-buffer-process buffer))) - (delete-region (point) (point-max)) - (insert (if answer "yes" "no")) - (comint-send-input)) - (set-buffer b)))) - -(defun gdb-sentinel (proc msg) - (cond ((null (buffer-name (process-buffer proc))) - ;; buffer killed - ;; Stop displaying an arrow in a source file. - ;(setq overlay-arrow-position nil) -- done by kill-buffer-hook - (set-process-buffer proc nil)) - ((memq (process-status proc) '(signal exit)) - ;; Stop displaying an arrow in a source file. - (gdb-delete-arrow-extent) - ;; Fix the mode line. - (setq modeline-process - (concat ": gdb " (symbol-name (process-status proc)))) - (let* ((obuf (current-buffer))) - ;; save-excursion isn't the right thing if - ;; process-buffer is current-buffer - (unwind-protect - (progn - ;; Write something in *compilation* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) - (if (eobp) - (insert ?\n mode-name " " msg) - (save-excursion - (goto-char (point-max)) - (insert ?\n mode-name " " msg))) - ;; If buffer and mode line will show that the process - ;; is dead, we can delete it now. Otherwise it - ;; will stay around until M-x list-processes. - (delete-process proc)) - ;; Restore old buffer, but don't restore old point - ;; if obuf is the gdb buffer. - (set-buffer obuf)))))) - - -(defun gdb-refresh (&optional arg) - "Fix up a possibly garbled display, and redraw the arrow." - (interactive "P") - (recenter arg) - (gdb-display-frame)) - -(defun gdb-display-frame (&optional nodisplay noauto) - "Find, obey and delete the last filename-and-line marker from GDB. -The marker looks like \\032\\032FILENAME:LINE:CHARPOS\\n. -Obeying it means displaying in another window the specified file and line." - (interactive) - (gdb-set-buffer) - (and gdb-last-frame (not nodisplay) - gdb-display-mode - (or (not gdb-last-frame-displayed-p) (not noauto)) - (progn (gdb-display-line (car gdb-last-frame) (cdr gdb-last-frame)) - (setq gdb-last-frame-displayed-p t)))) - -;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen -;; and that its line LINE is visible. -;; Put the overlay-arrow on the line LINE in that buffer. - -(defun gdb-display-line (true-file line &optional select-method) - ;; FILE to display - ;; LINE number to highlight and make visible - ;; SELECT-METHOD 'source, 'debugger, or 'none. (default is 'debugger) - (and (null select-method) (setq select-method 'debugger)) - (let* ((pre-display-buffer-function nil) ; screw it, put it all in one screen - (pop-up-windows t) - (source-buffer (find-file-noselect true-file)) - (source-window (display-buffer source-buffer)) - (debugger-window (get-buffer-window current-gdb-buffer)) - (extent gdb-arrow-extent) - pos) - ;; XEmacs change: make sure we find a window displaying the source file - ;; even if we are already sitting in it when a breakpoint is hit. - ;; Otherwise the t argument to display-buffer will prevent it from being - ;; displayed. - (save-excursion - (cond ((eq select-method 'debugger) - ;; might not already be displayed - (setq debugger-window (display-buffer current-gdb-buffer)) - (select-window debugger-window)) - ((eq select-method 'source) - (select-window source-window)))) - (and extent - (not (eq (extent-object extent) source-buffer)) - (setq extent (delete-extent extent))) - (or extent - (progn - (setq extent (make-extent 1 1 source-buffer)) - (set-extent-face extent 'gdb-arrow-face) - (set-extent-begin-glyph extent gdb-arrow-glyph) - (set-extent-begin-glyph-layout extent 'whitespace) - (set-extent-priority extent 2000) - (setq gdb-arrow-extent extent))) - (save-current-buffer - (set-buffer source-buffer) - (save-restriction - (widen) - (goto-line line) - (set-window-point source-window (point)) - (setq pos (point)) - (end-of-line) - (set-extent-endpoints extent pos (point)) - (run-hook-with-args 'gdb-arrow-extent-hooks extent)) - (cond ((or (< pos (point-min)) (> pos (point-max))) - (widen) - (goto-char pos)))) - ;; Added by Stig. It caused lots of problems for several users - ;; and since its purpose is unclear it is getting commented out. - ;;(and debugger-window - ;; (set-window-point debugger-window pos)) - )) - -(defun gdb-call (command) - "Invoke gdb COMMAND displaying source in other window." - (interactive) - (goto-char (point-max)) - ;; Record info on the last prompt in the buffer and its position. - ;; This is used in gdb-maybe-delete-prompt - ;; to prevent multiple prompts from accumulating. - (save-excursion - (goto-char (process-mark (get-buffer-process current-gdb-buffer))) - (let ((pt (point))) - (beginning-of-line) - (setq gdb-delete-prompt-marker - (if (= (point) pt) - nil - (list (point-marker) (- pt (point)) - (buffer-substring (point) pt)))))) - (gdb-set-buffer) - (process-send-string (get-buffer-process current-gdb-buffer) - (concat command "\n"))) - -(defun gdb-maybe-delete-prompt () - (if gdb-delete-prompt-marker - ;; Get the string that we used as the prompt before. - (let ((prompt (nth 2 gdb-delete-prompt-marker)) - (length (nth 1 gdb-delete-prompt-marker))) - ;; Position after it. - (goto-char (+ (car gdb-delete-prompt-marker) length)) - ;; Delete any duplicates of it which follow right after. - (while (and (<= (+ (point) length) (point-max)) - (string= prompt - (buffer-substring (point) (+ (point) length)))) - (delete-region (point) (+ (point) length))) - ;; If that didn't take us to where output is arriving, - ;; we have encountered something other than a prompt, - ;; so stop trying to delete any more prompts. - (if (not (= (point) - (process-mark (get-buffer-process current-gdb-buffer)))) - (progn - (set-marker (car gdb-delete-prompt-marker) nil) - (setq gdb-delete-prompt-marker nil)))))) - -(defun gdb-break (temp) - "Set GDB breakpoint at this source line. With ARG set temporary breakpoint." - (interactive "P") - (let* ((file-name (file-name-nondirectory buffer-file-name)) - (line (save-restriction - (widen) - (beginning-of-line) - (1+ (count-lines 1 (point))))) - (cmd (concat (if temp "tbreak " "break ") file-name ":" - (int-to-string line)))) - (set-buffer current-gdb-buffer) - (goto-char (process-mark (get-buffer-process current-gdb-buffer))) - (delete-region (point) (point-max)) - (insert cmd) - (comint-send-input) - ;;(process-send-string (get-buffer-process current-gdb-buffer) cmd) - )) - -(defun gdb-clear () - "Set GDB breakpoint at this source line." - (interactive) - (let* ((file-name (file-name-nondirectory buffer-file-name)) - (line (save-restriction - (widen) - (beginning-of-line) - (1+ (count-lines 1 (point))))) - (cmd (concat "clear " file-name ":" - (int-to-string line)))) - (set-buffer current-gdb-buffer) - (goto-char (process-mark (get-buffer-process current-gdb-buffer))) - (delete-region (point) (point-max)) - (insert cmd) - (comint-send-input) - ;;(process-send-string (get-buffer-process current-gdb-buffer) cmd) - )) - -(defun gdb-read-address() - "Return a string containing the core-address found in the buffer at point." - (save-excursion - (let ((pt (point)) found begin) - (setq found (if (search-backward "0x" (- pt 7) t)(point))) - (cond (found (forward-char 2) - (buffer-substring found - (progn (re-search-forward "[^0-9a-f]") - (forward-char -1) - (point)))) - (t (setq begin (progn (re-search-backward "[^0-9]") (forward-char 1) - (point))) - (forward-char 1) - (re-search-forward "[^0-9]") - (forward-char -1) - (buffer-substring begin (point))))))) - - -(defvar gdb-commands nil - "List of strings or functions used by send-gdb-command. -It is for customization by you.") - -(defun send-gdb-command (arg) - - "This command reads the number where the cursor is positioned. It - then inserts this ADDR at the end of the gdb buffer. A numeric arg - selects the ARG'th member COMMAND of the list gdb-print-command. If - COMMAND is a string, (format COMMAND ADDR) is inserted, otherwise - (funcall COMMAND ADDR) is inserted. eg. \"p (rtx)%s->fld[0].rtint\" - is a possible string to be a member of gdb-commands. " - - - (interactive "P") - (let (comm addr) - (if arg (setq comm (nth arg gdb-commands))) - (setq addr (gdb-read-address)) - (if (eq (current-buffer) current-gdb-buffer) - (set-mark (point))) - (cond (comm - (setq comm - (if (stringp comm) (format comm addr) (funcall comm addr)))) - (t (setq comm addr))) - (switch-to-buffer current-gdb-buffer) - (goto-char (point-max)) - (insert comm))) - -(fset 'gdb-control-c-subjob 'comint-interrupt-subjob) - -;(defun gdb-control-c-subjob () -; "Send a Control-C to the subprocess." -; (interactive) -; (process-send-string (get-buffer-process (current-buffer)) -; "\C-c")) - -(defun gdb-toolbar-break () - (interactive) - (save-excursion - (message (car gdb-last-frame)) - (set-buffer (find-file-noselect (car gdb-last-frame))) - (gdb-break nil))) - -(defun gdb-toolbar-clear () - (interactive) - (save-excursion - (message (car gdb-last-frame)) - (set-buffer (find-file-noselect (car gdb-last-frame))) - (gdb-clear))) - -(provide 'gdb) - -;;; gdb.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/gdbsrc.el --- a/lisp/comint/gdbsrc.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,896 +0,0 @@ -;;; gdbsrc.el -- Source-based (as opposed to comint-based) debugger -;; interaction mode eventually, this will be unified with GUD -;; (after gud works reliably w/ XEmacs...) -;; Keywords: c, unix, tools, debugging - -;; Copyright (C) 1990 Debby Ayers , and -;; Rich Schaefer -;; Copyright (C) 1994, 1995 Tinker Systems and INS Engineering Corp. -;; -;; This file is part of XEmacs. -;; -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2 of the License, or -;; (at your option) any later version. -;; -;; XEmacs 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 XEmacs; if not, write to the Free Software -;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -;; Based upon code for version18 by Debra Ayers - -;;; GDBSRC:: -;;; Gdbsrc extends the emacs GDB interface to accept gdb commands issued -;;; from the source code buffer. Gdbsrc behaves similar to gdb except -;;; now most debugging may be done from the source code using the *gdb* -;;; buffer to view output. Supports a point and click model under X to -;;; evaluate source code expressions (no more typing long variable names). -;;; -;;; Supports C source at the moment but C++ support will be added if there -;;; is sufficient interest. -;;; - -;; GDBSRC::Gdb Source Mode Interface description. -;; Gdbsrc extends the emacs GDB interface to accept gdb commands issued -;; from the source code buffer. Gdbsrc behaves similar to gdb except now all -;; debugging may be done from the currently focused source buffer using -;; the *gdb* buffer to view output. - -;; When source files are displayed through gdbsrc, buffers are put in -;; gdbsrc-mode minor mode. This mode puts the buffer in read-only state -;; and sets up a special key and mouse map to invoke communication with -;; the current gdb process. The minor mode may be toggled on/off as needed. -;; (ESC-T) - -;; C-expressions may be evaluated by gdbsrc by simply pointing at text in the -;; current source buffer with the mouse or by centering the cursor over text -;; and typing a single key command. ('p' for print, '*' for print *). - -;; As code is debugged and new buffers are displayed, the focus of gdbsrc -;; follows to each new source buffer. Makes debugging fun. (sound like a -;; commercial or what!) -;; - -;; Current Listing :: -;;key binding Comment -;;--- ------- ------- -;; -;; r gdb-return-from-src GDB return command -;; n gdb-next-from-src GDB next command -;; b gdb-back-from-src GDB back command -;; w gdb-where-from-src GDB where command -;; f gdb-finish-from-src GDB finish command -;; u gdb-up-from-src GDB up command -;; d gdb-down-from-src GDB down command -;; c gdb-cont-from-src GDB continue command -;; i gdb-stepi-from-src GDB step instruction command -;; s gdb-step-from-src GDB step command -;; ? gdb-whatis-c-sexp GDB whatis command for data at -;; buffer point -;; x gdbsrc-delete GDB Delete all breakpoints if no arg -;; given or delete arg (C-u arg x) -;; m gdbsrc-frame GDB Display current frame if no arg, -;; given or display frame arg -;; * gdb-*print-c-sexp GDB print * command for data at -;; buffer point -;; ! gdbsrc-goto-gdb Goto the GDB output buffer -;; p gdb-print-c-sexp GDB print * command for data at -;; buffer point -;; g gdbsrc-goto-gdb Goto the GDB output buffer -;; t gdbsrc-mode Toggles Gdbsrc mode (turns it off) -;; -;; C-c C-f gdb-finish-from-src GDB finish command -;; -;; C-x SPC gdb-break Set break for line with point -;; ESC t gdbsrc-mode Toggle Gdbsrc mode -;; -;; Local Bindings for buffer when you exit Gdbsrc minor mode -;; -;; C-x SPC gdb-break Set break for line with point -;; ESC t gdbsrc-mode Toggle Gdbsrc mode -;; - -;;; (eval-when-compile -;;; (or noninteractive -;;; (progn -;;; (message "ONLY compile gdbsrc except with -batch because of advice") -;;; (ding) -;;; ))) - -(require 'gdb "gdb") ; NOT gud! (yet...) - -(defvar gdbsrc-active-p t - "*Set to nil if you do not want source files put in gdbsrc-mode") - -(defvar gdbsrc-call-p nil - "True if gdb command issued from a source buffer") - -(defvar gdbsrc-associated-buffer nil - "Buffer name of attached gdb process") - -(defvar gdbsrc-mode nil - "Indicates whether buffer is in gdbsrc-mode or not") -(make-variable-buffer-local 'gdbsrc-mode) - -(defvar gdbsrc-global-mode nil - "Indicates whether global gdbsrc bindings are in effect or not") - -(defvar gdb-prompt-pattern "^[^)#$%>\n]*[)#$%>] *" - "A regexp for matching the end of the gdb prompt") - -;;; bindings - -(defvar gdbsrc-global-map - (let ((map (make-sparse-keymap))) - (set-keymap-name map 'gdbsrc-global-map) - (define-key map "\C-x " 'gdb-break) - (define-key map "\M-\C-t" 'gdbsrc-mode) - (define-key map "\M-\C-g" 'gdbsrc-goto-gdb) - - ;; middle button to select and print expressions... - (define-key map '(meta button2) 'gdbsrc-print-csexp) - (define-key map '(meta shift button2) 'gdbsrc-*print-csexp) - ;; left button to position breakpoints - (define-key map '(meta button1) 'gdbsrc-set-break) - (define-key map '(meta shift button1) 'gdbsrc-set-tbreak-continue) - map) - "Global minor keymap that is active whenever gdbsrc is running.") - -(add-minor-mode 'gdbsrc-global-mode " GdbGlobal" gdbsrc-global-map) - -(defvar gdbsrc-mode-map - (let ((map (make-sparse-keymap))) - (suppress-keymap map) - (set-keymap-name map 'gdbsrc-mode-map) - ;; inherit keys from global gdbsrc map just in case that somehow gets turned off. - (set-keymap-parents map (list gdbsrc-global-map)) - (define-key map "\C-x\C-q" 'gdbsrc-mode) ; toggle read-only - (define-key map "\C-c\C-c" 'gdbsrc-mode) - (define-key map "b" 'gdb-break) - (define-key map "g" 'gdbsrc-goto-gdb) - (define-key map "!" 'gdbsrc-goto-gdb) - (define-key map "p" 'gdb-print-c-sexp) - (define-key map "*" 'gdb-*print-c-sexp) - (define-key map "?" 'gdb-whatis-c-sexp) - (define-key map "R" 'gdbsrc-reset) - map) - "Minor keymap for buffers in gdbsrc-mode") - -(add-minor-mode 'gdbsrc-mode " GdbSrc" gdbsrc-mode-map) - -(defvar gdbsrc-toolbar - '([eos::toolbar-stop-at-icon - gdb-break - t - "Stop at selected position"] - [eos::toolbar-stop-in-icon - gdb-break - t - "Stop in function whose name is selected"] - [eos::toolbar-clear-at-icon - gdbsrc-delete - t - "Clear at selected position"] - [eos::toolbar-evaluate-icon - gdb-print-c-sexp - t - "Evaluate selected expression; shows in separate XEmacs frame"] - [eos::toolbar-evaluate-star-icon - gdb-*print-c-sexp - t - "Evaluate selected expression as a pointer; shows in separate XEmacs frame"] - [eos::toolbar-run-icon - gdbsrc-run - t - "Run current program"] - [eos::toolbar-cont-icon - gdbsrc-cont - t - "Continue current program"] - [eos::toolbar-step-into-icon - gdbsrc-step - t - "Step into (aka step)"] - [eos::toolbar-step-over-icon - gdbsrc-next - t - "Step over (aka next)"] - [eos::toolbar-up-icon - gdbsrc-up - t - "Stack Up (towards \"cooler\" - less recently visited - frames)"] - [eos::toolbar-down-icon - gdbsrc-down - t - "Stack Down (towards \"warmer\" - more recently visited - frames)"] - [eos::toolbar-fix-icon - nil - nil - "Fix (not available with gdb)"] - [eos::toolbar-build-icon - toolbar-compile - t - "Build (aka make -NYI)"] - )) - -(defmacro def-gdb-from-src (gdb-command key &optional doc &rest forms) - "Create a function that will call GDB-COMMAND with KEY." - (let* ((fname (format "gdbsrc-%s" gdb-command)) - (cstr (list 'if 'arg - (list 'format "%s %s" gdb-command '(prefix-numeric-value arg)) - gdb-command)) - fun) - (while (string-match " " fname) - (aset fname (match-beginning 0) ?-)) - (setq fun (intern fname)) - - (list 'progn - (nconc (list 'defun fun '(arg) - (or doc "") - '(interactive "P") - (list 'gdb-call-from-src cstr)) - forms) - (list 'define-key 'gdbsrc-mode-map key (list 'quote fun))))) - -(def-gdb-from-src "step" "s" "Step one instruction in src" - (gdb-delete-arrow-extent)) -(def-gdb-from-src "stepi" "i" "Step one source line (skip functions)" - (gdb-delete-arrow-extent)) -(def-gdb-from-src "cont" "c" "Continue with display" - (gdb-delete-arrow-extent)) -(def-gdb-from-src "down" "d" "Go down N stack frames (numeric arg) ") -(def-gdb-from-src "up" "u" "Go up N stack frames (numeric arg)") -(def-gdb-from-src "finish" "f" "Finish frame") -(def-gdb-from-src "where" "w" "Display (N frames of) backtrace") -(def-gdb-from-src "next" "n" "Step one line with display" - (gdb-delete-arrow-extent)) -(def-gdb-from-src "run" "r" "Run program from start" - (gdb-delete-arrow-extent)) -(def-gdb-from-src "return" "R" "Return from selected stack frame") -(def-gdb-from-src "disable" "x" "Disable all breakpoints") -(def-gdb-from-src "delete" "X" "Delete all breakpoints") -(def-gdb-from-src "quit" "Q" "Quit gdb." - (gdb-delete-arrow-extent)) -(def-gdb-from-src "info locals" "l" "Show local variables") -(def-gdb-from-src "info break" "B" "Show breakpoints") -(def-gdb-from-src "" "\r" "Repeat last command") -(def-gdb-from-src "frame" "m" "Show frame if no arg, with arg go to frame") - -;;; code - -;;;###autoload -(defun gdbsrc (path &optional core-or-pid) - "Activates a gdb session with gdbsrc-mode turned on. A numeric prefix -argument can be used to specify a running process to attach, and a non-numeric -prefix argument will cause you to be prompted for a core file to debug." - (interactive (let ((file (read-file-name "Program to debug: " nil nil t))) - (cond ((numberp current-prefix-arg) - (list file (int-to-string current-prefix-arg))) - (current-prefix-arg - (list file (read-file-name "Core file: " nil nil t))) - (t (list file))) - )) - ;; FIXME - this is perhaps an uncool thing to do --Stig - (delete-other-windows) - (split-window-vertically) - (other-window 0) - - (gdb path core-or-pid) - (local-set-key 'button2 'gdbsrc-select-or-yank) - (setq mode-motion-hook 'gdbsrc-mode-motion) - ;; XEmacs change: - (make-local-hook 'kill-buffer-hook) - (add-hook 'kill-buffer-hook 'gdbsrc-reset nil t)) - -(defun gdbsrc-global-mode () - ;; this can be used as a hook for gdb-mode.... - (or current-gdb-buffer - (and (eq major-mode 'gdb-mode) ; doesn't work w/ energize yet - (setq current-gdb-buffer (current-buffer)) - ;; XEmacs change: - (progn - (make-local-hook 'kill-buffer-hook) - (add-hook 'kill-buffer-hook 'gdbsrc-reset nil t))) - (error "Cannot determine current-gdb-buffer")) -;;; (set-process-filter -;;; (get-buffer-process current-gdb-buffer) 'gdbsrc-mode-filter) -;;; (set-process-sentinel -;;; (get-buffer-process current-gdb-buffer) 'gdbsrc-mode-sentinel) - ;; gdbsrc-global-mode was set to t here but that tended to piss - ;; people off - (setq gdbsrc-global-mode nil - gdbsrc-active-p t - gdbsrc-call-p nil - gdbsrc-mode nil) - (message "Gbd source mode active")) - -(add-hook 'gdb-mode-hook 'gdbsrc-global-mode) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Gdb Source minor mode. -;;; - -(defvar gdbsrc-associated-buffer nil - "The gdb buffer to send commands to.") -(defvar gdbsrc-initial-readonly 'undefined - "read-only status of buffer when not in gdbsrc-mode") -(defvar gdbsrc-old-toolbar nil - "saved toolbar for buffer") - -(defun gdbsrc-mode (arg &optional quiet) - "Minor mode for interacting with gdb from a c source file. -With arg, turn gdbsrc-mode on iff arg is positive. In gdbsrc-mode, -you may send an associated gdb buffer commands from the current buffer -containing c source code." - (interactive "P") - (setq gdbsrc-mode - (if (null arg) - (not gdbsrc-mode) - (> (prefix-numeric-value arg) 0))) - - (cond (gdbsrc-mode - (cond ((not (local-variable-p 'gdbsrc-initial-readonly (current-buffer))) - (set (make-local-variable 'gdbsrc-initial-readonly) - buffer-read-only) - (set (make-local-variable 'gdbsrc-associated-buffer) - current-gdb-buffer) - (if (featurep 'toolbar) - (set (make-local-variable 'gdbsrc-old-toolbar) - (specifier-specs default-toolbar (current-buffer)))) - ) - ) - (if (featurep 'toolbar) - (set-specifier default-toolbar (cons (current-buffer) - gdbsrc-toolbar))) - (setq buffer-read-only t) - (or quiet (message "Entering gdbsrc-mode..."))) - (t - (and (local-variable-p 'gdbsrc-initial-readonly (current-buffer)) - (progn - (if (featurep 'toolbar) - (if gdbsrc-old-toolbar - (set-specifier default-toolbar - (cons (current-buffer) - gdbsrc-old-toolbar)) - (remove-specifier default-toolbar (current-buffer)))) - (kill-local-variable 'gdbsrc-old-toolbar) - (setq buffer-read-only gdbsrc-initial-readonly) - (kill-local-variable 'gdbsrc-initial-readonly) - (kill-local-variable 'gdbsrc-associated-buffer) - )) - (or quiet (message "Exiting gdbsrc-mode...")))) - (redraw-modeline t)) - -;; -;; Sends commands to gdb process. - -(defun gdb-call-from-src (command) - "Send associated gdb process COMMAND displaying source in this window." - (setq gdbsrc-call-p t) - (let ((src-win (selected-window)) - (buf (or gdbsrc-associated-buffer current-gdb-buffer))) - (or (buffer-name buf) - (error "GDB buffer deleted")) - (pop-to-buffer buf) - (goto-char (point-max)) - (beginning-of-line) - ;; Go past gdb prompt - (re-search-forward - gdb-prompt-pattern (save-excursion (end-of-line) (point)) t) - ;; Delete any not-supposed-to-be-there text - (delete-region (point) (point-max)) - (insert command) - (comint-send-input) - (select-window src-win) - )) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; Define Commands for GDB SRC Mode Buffer -;;; - -;;; ;; #### - move elsewhere -(or (fboundp 'event-buffer) - (defun event-buffer (event) - "Return buffer assocaited with EVENT, or nil." - (let ((win (event-window event))) - (and win (window-buffer win))))) - -(defun set-gdbsrc-mode-motion-extent (st en action) - ;; by Stig@hackvan.com - (let ((ex (make-extent st en))) - (set-extent-face ex 'highlight) - (set-extent-property ex 'gdbsrc t) - (set-extent-property ex 'action action) - (setq mode-motion-extent ex))) - -(defun nuke-mode-motion-extent () - ;; by Stig@hackvan.com - (cond (mode-motion-extent - (delete-extent mode-motion-extent) - (setq mode-motion-extent nil)))) - -(defun looking-at-any (regex-list) - ;; by Stig@hackvan.com - (catch 'found - (while regex-list - (and (looking-at (car regex-list)) - (throw 'found t)) - (setq regex-list (cdr regex-list))))) - -(defconst gdb-breakpoint-patterns - '( - ;; when execution stops... - ;;Breakpoint 1, XlwMenuRedisplay (w=0x4d2e00, ev=0xefffe3f8, region=0x580e60) - ;; at /net/stig/src/xemacs/lwlib/xlwmenu.c:2518 - "^[BW][ra][et][ac][kh]point [0-9]+, .*\\(\n\\s .*\\)*" - ;; output of the breakpoint command: - ;;Breakpoint 1 at 0x19f5c8: file /net/stig/src/xemacs/lwlib/xlwmenu.c, line 2715. - "^[BW][ra][et][ac][kh]point [0-9]+ at .*: file \\([^ ,\n]+\\), line \\([0-9]+\\)." - ;;Num Type Disp Enb Address What - ;;1 breakpoint keep y 0x0019ee60 in XlwMenuRedisplay - ;; at /net/stig/src/xemacs/lwlib/xlwmenu.c:2518 - "^[0-9]+\\s +[bw][ra][et][ac][kh]point.* in .*\\(\n\\s +\\)?at [^ :\n]+:[0-9]+\\(\n\\s .*\\)*" - ) - "list of patterns to match gdb's various ways of displaying a breakpoint") - -(defun gdbsrc-make-breakpoint-action (string) - ;; by Stig@hackvan.com - (if (or (string-match "file \\([^ ,\n]+\\), line \\([0-9]+\\)" string) - (string-match "at \\([^ :\n]+\\):\\([0-9]+\\)" string)) - (list 'gdbsrc-display - (match-string 1 string) - (string-to-int (match-string 2 string))))) - -(defconst gdb-stack-frame-pattern - ;;#9 0x62f08 in emacs_Xt_next_event (emacs_event=0x4cf804) - ;; at /net/stig/src/xemacs/src/event-Xt.c:1778 - "^#\\([0-9]+\\)\\s +\\(0x[0-9a-f]+ in .*\\|.*\\sw+.* (.*) at .*\\)\\(\n\\s .*\\)*" - "matches the first line of a gdb stack frame and all continuation lines. -subex 1 is frame number.") - -(defun gdbsrc-mode-motion (ee) - ;; by Stig@hackvan.com - (save-excursion - (set-buffer (event-buffer ee)) - (save-excursion - (if (not (event-point ee)) - (nuke-mode-motion-extent) - (goto-char (event-point ee)) - (beginning-of-line) - (while (and (not (bobp)) (eq ? (char-syntax (following-char)))) - (forward-line -1)) - (if (extent-at (point) (current-buffer) 'gdbsrc) - nil - (nuke-mode-motion-extent) - (cond ((looking-at-any gdb-breakpoint-patterns) - (set-gdbsrc-mode-motion-extent - (match-beginning 0) - (match-end 0) - (gdbsrc-make-breakpoint-action (match-string 0)))) - ((looking-at gdb-stack-frame-pattern) - (set-gdbsrc-mode-motion-extent - (match-beginning 0) - (match-end 0) - (list 'gdbsrc-frame - (string-to-int (match-string 1))))) - ))) - ))) - -(defun gdbsrc-display (file line) - ;; by Stig@hackvan.com - (select-window (display-buffer (find-file-noselect file))) - (goto-line line)) - -(defun click-inside-selection-p (click) - (or (click-inside-extent-p click primary-selection-extent) - (click-inside-extent-p click zmacs-region-extent) - )) - -(defun click-inside-extent-p (click extent) - "Returns non-nil if the button event is within the bounds of the primary -selection-extent, nil otherwise." - ;; stig@hackvan.com - (let ((ewin (event-window click)) - (epnt (event-point click))) - (and ewin - epnt - extent - (eq (window-buffer ewin) - (extent-object extent)) - (extent-start-position extent) - (> epnt (extent-start-position extent)) - (> (extent-end-position extent) epnt)))) - -(defun point-inside-extent-p (extent) - "Returns non-nil if the point is within or just after the bounds of the -primary selection-extent, nil otherwise." - ;; stig@hackvan.com - (and extent ; FIXME - I'm such a sinner... - (eq (current-buffer) - (extent-object extent)) - (> (point) (extent-start-position extent)) - (>= (extent-end-position extent) (point)))) - -(defun gdbsrc-select-or-yank (ee) - ;; by Stig@hackvan.com - (interactive "e") - (let ((action (save-excursion - (set-buffer (event-buffer ee)) - (and mode-motion-extent - (click-inside-extent-p ee mode-motion-extent) - (extent-property mode-motion-extent 'action))) - )) - (if action - (eval action) - (mouse-yank ee)))) - -(defvar gdb-print-format "" - "Set this variable to a valid format string to print c-sexps in a -different way (hex,octal, etc).") - -(defun gdb-print-c-sexp () - "Find the nearest c-mode sexp. Send it to gdb with print command." - (interactive) - (let* ((tag (find-c-sexp)) - (command (concat "print " gdb-print-format tag))) - (gdb-call-from-src command))) - -(defun gdb-*print-c-sexp () - "Find the nearest c-mode sexp. Send it to gdb with the print * command." - (interactive) - (let* ((tag (find-c-sexp)) - (command (concat "print " gdb-print-format "*" tag))) - (gdb-call-from-src command))) - -(defun gdb-whatis-c-sexp () - "Find the nearest c-mode sexp. Send it to gdb with the whatis command. " - (interactive) - (let* ((tag (gdbsrc-selection-or-sexp)) - (command (concat "whatis " tag))) - (gdb-call-from-src command))) - -(defun gdbsrc-goto-gdb () - "Hop back and forth between the gdb interaction buffer and the gdb source -buffer. " - ;; by Stig@hackvan.com - (interactive) - (let ((gbuf (or gdbsrc-associated-buffer current-gdb-buffer))) - (cond ((eq (current-buffer) gbuf) - (and gdb-arrow-extent - (extent-object gdb-arrow-extent) - (progn (pop-to-buffer (extent-object gdb-arrow-extent)) - (goto-char (extent-start-position gdb-arrow-extent))))) - ((buffer-name gbuf) (pop-to-buffer gbuf)) - ((y-or-n-p "No debugger. Start a new one? ") - (call-interactively 'gdbsrc)) - (t (error "No gdb buffer.")) - ))) - -(defvar gdbsrc-last-src-buffer nil) - -(defun gdbsrc-goto-src () - (interactive) - (let* ((valid (and gdbsrc-last-src-buffer - (memq gdbsrc-last-src-buffer (buffer-list)))) - (win (and valid - (get-buffer-window gdbsrc-last-src-buffer)))) - (cond (win (select-window win)) - (valid (pop-to-buffer gdbsrc-last-src-buffer))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; -;;; The following functions are used to extract the closest surrounding -;;; c expression from point -;;; -(defun back-sexp () - "Version of backward-sexp that catches errors" - (condition-case nil - (backward-sexp) - (error t))) - -(defun forw-sexp () - "Version of forward-sexp that catches errors" - (condition-case nil - (forward-sexp) - (error t))) - -(defun sexp-compound-sep (span-start span-end) - "Returns '.' for '->' & '.', returns ' ' for white space, -returns '?' for other puctuation" - (let ((result ? ) - (syntax)) - (while (< span-start span-end) - (setq syntax (char-syntax (char-after span-start))) - (cond - ((= syntax ? ) t) - ((= syntax ?.) (setq syntax (char-after span-start)) - (cond - ((= syntax ?.) (setq result ?.)) - ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>)) - (setq result ?.) - (setq span-start (+ span-start 1))) - (t (setq span-start span-end) - (setq result ??))))) - (setq span-start (+ span-start 1))) - result - ) - ) - -(defun sexp-compound (first second) - "Returns non-nil if the concatenation of two S-EXPs result in a Single C -token. The two S-EXPs are represented as a cons cells, where the car -specifies the point in the current buffer that marks the begging of the -S-EXP and the cdr specifies the character after the end of the S-EXP -Link S-Exps of the form: - Sexp -> SexpC - Sexp . Sexp - Sexp (Sexp) Maybe exclude if first Sexp is: if, while, do, for, switch - Sexp [Sexp] - (Sexp) Sexp - [Sexp] Sexp" - (let ((span-start (cdr first)) - (span-end (car second)) - (syntax)) - (setq syntax (sexp-compound-sep span-start span-end)) - (cond - ((= (car first) (car second)) nil) - ((= (cdr first) (cdr second)) nil) - ((= syntax ?.) t) - ((= syntax ? ) - (setq span-start (char-after (- span-start 1))) - (setq span-end (char-after span-end)) - (cond - ((= span-start ?) ) t ) - ((= span-start ?] ) t ) - ((= span-end ?( ) t ) - ((= span-end ?[ ) t ) - (t nil)) - ) - (t nil)) - ) - ) - -(defun sexp-cur () - "Returns the S-EXP that Point is a member, Point is set to begging of S-EXP. -The S-EXPs is represented as a cons cell, where the car specifies the point in -the current buffer that marks the begging of the S-EXP and the cdr specifies -the character after the end of the S-EXP" - (let ((p (point)) (begin) (end)) - (back-sexp) - (setq begin (point)) - (forw-sexp) - (setq end (point)) - (if (>= p end) - (progn - (setq begin p) - (goto-char p) - (forw-sexp) - (setq end (point)) - ) - ) - (goto-char begin) - (cons begin end) - ) - ) - -(defun sexp-prev () - "Returns the previous S-EXP, Point is set to begging of that S-EXP. -The S-EXPs is represented as a cons cell, where the car specifies the point in -the current buffer that marks the begging of the S-EXP and the cdr specifies -the character after the end of the S-EXP" - (let ((begin) (end)) - (back-sexp) - (setq begin (point)) - (forw-sexp) - (setq end (point)) - (goto-char begin) - (cons begin end)) -) - -(defun sexp-next () - "Returns the following S-EXP, Point is set to begging of that S-EXP. -The S-EXPs is represented as a cons cell, where the car specifies the point in -the current buffer that marks the begging of the S-EXP and the cdr specifies -the character after the end of the S-EXP" - (let ((begin) (end)) - (forw-sexp) - (forw-sexp) - (setq end (point)) - (back-sexp) - (setq begin (point)) - (cons begin end) - ) - ) - -(defun find-c-sexp () - "Returns the Complex S-EXP that surrounds Point" - (interactive) - (save-excursion - (let ((p) (sexp) (test-sexp)) - (setq p (point)) - (setq sexp (sexp-cur)) - (setq test-sexp (sexp-prev)) - (while (sexp-compound test-sexp sexp) - (setq sexp (cons (car test-sexp) (cdr sexp))) - (goto-char (car sexp)) - (setq test-sexp (sexp-prev)) - ) - (goto-char p) - (setq test-sexp (sexp-next)) - (while (sexp-compound sexp test-sexp) - (setq sexp (cons (car sexp) (cdr test-sexp))) - (setq test-sexp (sexp-next)) - ) - (buffer-substring (car sexp) (cdr sexp)) - ) - ) - ) - -(defun gdbsrc-selection-or-sexp (&optional ee) - ;; FIXME - fix this docstring - "If the EVENT is within the primary selection, then return the selected -text, otherwise parse the expression at the point of the mouse click and -return that. If EVENT is nil, then return the C sexp at point." - ;; stig@hackvan.com - (cond ((or (and ee (click-inside-selection-p ee)) - (and (not ee) (point-inside-selection-p))) - (replace-in-string (extent-string primary-selection-extent) "\n\\s *" " ")) - (ee - (gdbsrc-get-csexp-at-click ee)) - (t - (find-c-sexp)) - )) - -(defun gdbsrc-get-csexp-at-click (ee) - "Returns the containing s-expression located at the mouse cursor to point." - ;; " - ;; by Stig@hackvan.com - (let ((ewin (event-window ee)) - (epnt (event-point ee))) - (or (and ewin epnt) - (error "Must click within a window")) - (save-excursion - (set-buffer (window-buffer ewin)) - (save-excursion - (goto-char epnt) - (find-c-sexp))))) - -(defun gdbsrc-print-csexp (&optional ee) - (interactive) - (or ee (setq ee current-mouse-event)) - (gdb-call-from-src - (concat "print " gdb-print-format (gdbsrc-selection-or-sexp ee)))) - -(defun gdbsrc-*print-csexp (&optional ee) - (interactive) - (or ee (setq ee current-mouse-event)) - (gdb-call-from-src - (concat "print *" gdb-print-format (gdbsrc-selection-or-sexp ee)))) - -;; (defun gdbsrc-print-region (arg) -;; (let (( command (concat "print " gdb-print-format (x-get-cut-buffer)))) -;; (gdb-call-from-src command))) -;; -;; (defun gdbsrc-*print-region (arg) -;; (let (( command (concat "print *" gdb-print-format (x-get-cut-buffer)))) -;; (gdb-call-from-src command))) - -(defun gdbsrc-file:lno () - "returns \"file:lno\" specification for location of point. " - ;; by Stig@hackvan.com - (format "%s:%d" - (file-name-nondirectory buffer-file-name) - (save-restriction - (widen) - (1+ (count-lines (point-min) - (save-excursion (beginning-of-line) (point))))) - )) - -(defun gdbsrc-set-break (ee) - "Sets a breakpoint. Click on the selection and it will set a breakpoint -using the selected text. Click anywhere in a source file, and it will set -a breakpoint at that line number of that file." - ;; by Stig@hackvan.com - ;; there is already gdb-break, so this only needs to work with mouse clicks. - (interactive "e") - (gdb-call-from-src - (concat "break " - (if (click-inside-selection-p ee) - (extent-string primary-selection-extent) - (mouse-set-point ee) - (or buffer-file-name (error "No file in window")) - (gdbsrc-file:lno) - )))) - -(defun gdbsrc-set-tbreak-continue (&optional ee) - "Set a temporary breakpoint at the position of the mouse click and then -continues. This can be bound to either a key or a mouse button." - ;; by Stig@hackvan.com - (interactive) - (or ee (setq ee current-mouse-event)) - (and ee (mouse-set-point ee)) - (gdb-call-from-src (concat "tbreak " (gdbsrc-file:lno))) - (gdb-call-from-src "c")) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Functions extended from gdb.el for gdbsrc. -;; -;; gdbsrc-set-buffer - added a check to set buffer to gdbsrc-associated-buffer -;; to handle multiple gdb sessions being driven from src -;; files. - -(require 'advice) - -(defadvice gdb-set-buffer (after gdbsrc activate) ; () - "Advised to work from a source buffer instead of just the gdb buffer." - ;; by Stig@hackvan.com - ;; the operations below have tests which are disjoint from the tests in - ;; the original `gdb-set-buffer'. Current-gdb-buffer cannot be set twice. - (and gdbsrc-call-p - gdbsrc-associated-buffer - (setq current-gdb-buffer gdbsrc-associated-buffer))) - -(defadvice gdb-display-line (around gdbsrc activate) - ;; (true-file line &optional select-method) - "Advised to select the source buffer instead of the gdb-buffer" - ;; by Stig@hackvan.com - (ad-set-arg 2 'source) ; tell it not to select the gdb window - ad-do-it - (save-excursion - (let* ((buf (extent-object gdb-arrow-extent)) - (win (get-buffer-window buf))) - (setq gdbsrc-last-src-buffer buf) - (select-window win) - (set-window-point win (extent-start-position gdb-arrow-extent)) - (set-buffer buf)) - (and gdbsrc-active-p - (not gdbsrc-mode) - (not (eq (current-buffer) current-gdb-buffer)) - (gdbsrc-mode 1)))) - -(defadvice gdb-filter (after gdbsrc activate) ; (proc string) - ;; by Stig@hackvan.com - ;; if we got a gdb prompt and it wasn't a gdbsrc command, then it's gdb - ;; hitting a breakpoint or having a core dump, so bounce back to the gdb - ;; window. - (let* ((selbuf (window-buffer (selected-window))) - win) - ;; if we're at a gdb prompt, then display the buffer - (and (save-match-data (string-match gdb-prompt-pattern (ad-get-arg 1))) - (prog1 - (not gdbsrc-call-p) - (setq gdbsrc-call-p nil)) - (setq win (display-buffer current-gdb-buffer)) - ;; if we're not in either the source buffer or the gdb buffer, - ;; then select the window too... - (not (eq selbuf current-gdb-buffer)) - (not (eq selbuf gdbsrc-last-src-buffer)) - (progn - (ding nil 'warp) - (select-window win))) - )) - -(defun gdbsrc-reset () - ;; tidy house and turn off gdbsrc-mode in all buffers - ;; by Stig@hackvan.com - (gdb-delete-arrow-extent) - (setq gdbsrc-global-mode nil) - (mapcar #'(lambda (buffer) - (set-buffer buffer) - (cond ((eq gdbsrc-associated-buffer current-gdb-buffer) - (gdbsrc-mode -1)))) - (buffer-list))) - -(defadvice gdb-sentinel (after gdbsrc freeze) ; (proc msg) - ;; by Stig@hackvan.com - (gdbsrc-reset) - (message "Gdbsrc finished")) - -(provide 'gdbsrc) diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/gud.el --- a/lisp/comint/gud.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3230 +0,0 @@ -;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, or xdb -;;; under Emacs - -;; Author: Eric S. Raymond -;; Maintainer: FSF -;; Version: 1.3 -;; Keywords: c, unix, tools, debugging - -;; Copyright (C) 1992, 1993 Free Software Foundation, Inc. - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: - -;; The ancestral gdb.el was by W. Schelter -;; It was later rewritten by rms. Some ideas were due to Masanobu. -;; Grand Unification (sdb/dbx support) by Eric S. Raymond -;; The overloading code was then rewritten by Barry Warsaw , -;; who also hacked the mode to use comint.el. Shane Hartman -;; added support for xdb (HPUX debugger). - -;; Cygnus Support added support for gdb's --annotate=2. - -;;; Code: - -(require 'comint) -(require 'etags) - -;; ====================================================================== -;; GUD commands must be visible in C buffers visited by GUD - -(defvar gud-key-prefix "\C-x\C-a" - "Prefix of all GUD commands valid in C buffers.") - -(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh) -(global-set-key "\C-x " 'gud-break) ;; backward compatibility hack - -;; ====================================================================== -;; the overloading mechanism - -(defun gud-overload-functions (gud-overload-alist) - "Overload functions defined in GUD-OVERLOAD-ALIST. -This association list has elements of the form - (ORIGINAL-FUNCTION-NAME OVERLOAD-FUNCTION)" - (mapcar - (function (lambda (p) (fset (car p) (symbol-function (cdr p))))) - gud-overload-alist)) - -(defun gud-massage-args (file args) - (error "GUD not properly entered.")) - -(defun gud-marker-filter (str) - (error "GUD not properly entered.")) - -(defun gud-find-file (f) - (error "GUD not properly entered.")) - -;; ====================================================================== -;; command definition - -;; This macro is used below to define some basic debugger interface commands. -;; Of course you may use `gud-def' with any other debugger command, including -;; user defined ones. - -;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form -;; which defines FUNC to send the command NAME to the debugger, gives -;; it the docstring DOC, and binds that function to KEY in the GUD -;; major mode. The function is also bound in the global keymap with the -;; GUD prefix. - -(defmacro gud-def (func cmd key &optional doc) - "Define FUNC to be a command sending STR and bound to KEY, with -optional doc string DOC. Certain %-escapes in the string arguments -are interpreted specially if present. These are: - - %f name (without directory) of current source file. - %d directory of current source file. - %l number of current source line - %e text of the C lvalue or function-call expression surrounding point. - %a text of the hexadecimal address surrounding point - %p prefix argument to the command (if any) as a number - - The `current' source file is the file of the current buffer (if -we're in a C file) or the source file current at the last break or -step (if we're in the GUD buffer). - The `current' line is that of the current buffer (if we're in a -source file) or the source line number at the last break or step (if -we're in the GUD buffer)." - (list 'progn - (list 'defun func '(arg) - (or doc "") - '(interactive "p") - (list 'gud-call cmd 'arg)) - (if key - (list 'define-key - '(current-local-map) - (concat "\C-c" key) - (list 'quote func))) - (if key - (list 'global-set-key - (list 'concat 'gud-key-prefix key) - (list 'quote func))))) - -;; Where gud-display-frame should put the debugging arrow. This is -;; set by the marker-filter, which scans the debugger's output for -;; indications of the current program counter. -(defvar gud-last-frame nil) - -;; Used by gud-refresh, which should cause gud-display-frame to redisplay -;; the last frame, even if it's been called before and gud-last-frame has -;; been set to nil. -(defvar gud-last-last-frame nil) - -;; All debugger-specific information is collected here. -;; Here's how it works, in case you ever need to add a debugger to the mode. -;; -;; Each entry must define the following at startup: -;; -;; -;; comint-prompt-regexp -;; gud--massage-args -;; gud--marker-filter -;; gud--find-file -;; -;; The job of the massage-args method is to modify the given list of -;; debugger arguments before running the debugger. -;; -;; The job of the marker-filter method is to detect file/line markers in -;; strings and set the global gud-last-frame to indicate what display -;; action (if any) should be triggered by the marker. Note that only -;; whatever the method *returns* is displayed in the buffer; thus, you -;; can filter the debugger's output, interpreting some and passing on -;; the rest. -;; -;; The job of the find-file method is to visit and return the buffer indicated -;; by the car of gud-tag-frame. This may be a file name, a tag name, or -;; something else. - -;; ====================================================================== -;; gdb functions - -;;; History of argument lists passed to gdb. -(defvar gud-gdb-history nil) - -(defun gud-gdb-massage-args (file args) - (cons "--annotate=2" (cons file args))) - - -;; -;; In this world, there are gdb instance objects (of unspecified -;; representation) and buffers associated with those objects. -;; - -;; -;; gdb-instance objects -;; - -(defun make-gdb-instance (proc) - "Create a gdb instance object from a gdb process." - (setq last-proc proc) - (let ((instance (cons 'gdb-instance proc))) - (save-excursion - (set-buffer (process-buffer proc)) - (setq gdb-buffer-instance instance) - (progn - (mapcar 'make-variable-buffer-local gdb-instance-variables) - (setq gdb-buffer-type 'gud) - ;; If we're taking over the buffer of another process, - ;; take over it's ancillery buffers as well. - ;; - (let ((dead (or old-gdb-buffer-instance))) - (mapcar - (function - (lambda (b) - (progn - (set-buffer b) - (if (eq dead gdb-buffer-instance) - (setq gdb-buffer-instance instance))))) - (buffer-list))))) - instance)) - -(defun gdb-instance-process (inst) (cdr inst)) - -;;; The list of instance variables is built up by the expansions of -;;; DEF-GDB-VARIABLE -;;; -(defvar gdb-instance-variables '() - "A list of variables that are local to the gud buffer associated -with a gdb instance.") - -(defmacro def-gdb-variable - (name accessor setter &optional default doc) - (` - (progn - (defvar (, name) (, default) (, (or doc "undocumented"))) - (if (not (memq '(, name) gdb-instance-variables)) - (setq gdb-instance-variables - (cons '(, name) gdb-instance-variables))) - (, (and accessor - (` - (defun (, accessor) (instance) - (let - ((buffer (gdb-get-instance-buffer instance 'gud))) - (and buffer - (save-excursion - (set-buffer buffer) - (, name)))))))) - (, (and setter - (` - (defun (, setter) (instance val) - (let - ((buffer (gdb-get-instance-buffer instance 'gud))) - (and buffer - (save-excursion - (set-buffer buffer) - (setq (, name) val))))))))))) - -(defmacro def-gdb-var (root-symbol &optional default doc) - (let* ((root (symbol-name root-symbol)) - (accessor (intern (concat "gdb-instance-" root))) - (setter (intern (concat "set-gdb-instance-" root))) - (var-name (intern (concat "gdb-" root)))) - (` (def-gdb-variable - (, var-name) (, accessor) (, setter) - (, default) (, doc))))) - -(def-gdb-var buffer-instance nil - "In an instance buffer, the buffer's instance.") - -(def-gdb-var buffer-type nil - "One of the symbols bound in gdb-instance-buffer-rules") - -(def-gdb-var burst "" - "A string of characters from gdb that have not yet been processed.") - -(def-gdb-var input-queue () - "A list of high priority gdb command objects.") - -(def-gdb-var idle-input-queue () - "A list of low priority gdb command objects.") - -(def-gdb-var prompting nil - "True when gdb is idle with no pending input.") - -(def-gdb-var output-sink 'user - "The disposition of the output of the current gdb command. -Possible values are these symbols: - - user -- gdb output should be copied to the gud buffer - for the user to see. - - inferior -- gdb output should be copied to the inferior-io buffer - - pre-emacs -- output should be ignored util the post-prompt - annotation is received. Then the output-sink - becomes:... - emacs -- output should be collected in the partial-output-buffer - for subsequent processing by a command. This is the - disposition of output generated by commands that - gud mode sends to gdb on its own behalf. - post-emacs -- ignore input until the prompt annotation is - received, then go to USER disposition. -") - -(def-gdb-var current-item nil - "The most recent command item sent to gdb.") - -(def-gdb-var pending-triggers '() - "A list of trigger functions that have run later than their output -handlers.") - -(defun in-gdb-instance-context (instance form) - "Funcall `form' in the gud buffer of `instance'" - (save-excursion - (set-buffer (gdb-get-instance-buffer instance 'gud)) - (funcall form))) - -;; end of instance vars - -;; -;; finding instances -;; - -(defun gdb-proc->instance (proc) - (save-excursion - (set-buffer (process-buffer proc)) - gdb-buffer-instance)) - -(defun gdb-mru-instance-buffer () - "Return the most recently used (non-auxiliary) gdb gud buffer." - (save-excursion - (gdb-goto-first-gdb-instance (buffer-list)))) - -(defun gdb-goto-first-gdb-instance (blist) - "Use gdb-mru-instance-buffer -- not this." - (and blist - (progn - (set-buffer (car blist)) - (or (and gdb-buffer-instance - (eq gdb-buffer-type 'gud) - (car blist)) - (gdb-goto-first-gdb-instance (cdr blist)))))) - -(defun buffer-gdb-instance (buf) - (save-excursion - (set-buffer buf) - gdb-buffer-instance)) - -(defun gdb-needed-default-instance () - "Return the most recently used gdb instance or signal an error." - (let ((buffer (gdb-mru-instance-buffer))) - (or (and buffer (buffer-gdb-instance buffer)) - (error "No instance of gdb found.")))) - -(defun gdb-instance-target-string (instance) - "The apparent name of the program being debugged by a gdb instance. -For sure this the root string used in smashing together the gud -buffer's name, even if that doesn't happen to be the name of a -program." - (in-gdb-instance-context - instance - (function (lambda () gud-target-name)))) - - - -;; -;; Instance Buffers. -;; - -;; More than one buffer can be associated with a gdb instance. -;; -;; Each buffer has a TYPE -- a symbol that identifies the function -;; of that particular buffer. -;; -;; The usual gud interaction buffer is given the type `gud' and -;; is constructed specially. -;; -;; Others are constructed by gdb-get-create-instance-buffer and -;; named according to the rules set forth in the gdb-instance-buffer-rules-assoc - -(defun gdb-get-instance-buffer (instance key) - "Return the instance buffer for `instance' tagged with type `key'. -The key should be one of the cars in `gdb-instance-buffer-rules-assoc'." - (save-excursion - (gdb-look-for-tagged-buffer instance key (buffer-list)))) - -(defun gdb-get-create-instance-buffer (instance key) - "Create a new gdb instance buffer of the type specified by `key'. -The key should be one of the cars in `gdb-instance-buffer-rules-assoc'." - (or (gdb-get-instance-buffer instance key) - (let* ((rules (assoc key gdb-instance-buffer-rules-assoc)) - (name (funcall (gdb-rules-name-maker rules) instance)) - (new (get-buffer-create name))) - (save-excursion - (set-buffer new) - (make-variable-buffer-local 'gdb-buffer-type) - (setq gdb-buffer-type key) - (make-variable-buffer-local 'gdb-buffer-instance) - (setq gdb-buffer-instance instance) - (if (cdr (cdr rules)) - (funcall (car (cdr (cdr rules))))) - new)))) - -(defun gdb-rules-name-maker (rules) (car (cdr rules))) - -(defun gdb-look-for-tagged-buffer (instance key bufs) - (let ((retval nil)) - (while (and (not retval) bufs) - (set-buffer (car bufs)) - (if (and (eq gdb-buffer-instance instance) - (eq gdb-buffer-type key)) - (setq retval (car bufs))) - (setq bufs (cdr bufs)) - ) - retval)) - -(defun gdb-instance-buffer-p (buf) - (save-excursion - (set-buffer buf) - (and gdb-buffer-type - (not (eq gdb-buffer-type 'gud))))) - -;; -;; This assoc maps buffer type symbols to rules. Each rule is a list of -;; at least one and possible more functions. The functions have these -;; roles in defining a buffer type: -;; -;; NAME - take an instance, return a name for this type buffer for that -;; instance. -;; The remaining function(s) are optional: -;; -;; MODE - called in the new buffer with no arguments, should establish -;; the proper mode for the buffer. -;; - -(defvar gdb-instance-buffer-rules-assoc '()) - -(defun gdb-set-instance-buffer-rules (buffer-type &rest rules) - (let ((binding (assoc buffer-type gdb-instance-buffer-rules-assoc))) - (if binding - (setcdr binding rules) - (setq gdb-instance-buffer-rules-assoc - (cons (cons buffer-type rules) - gdb-instance-buffer-rules-assoc))))) - -(gdb-set-instance-buffer-rules 'gud 'error) ; gud buffers are an exception to the rules - -;; -;; partial-output buffers -;; -;; These accumulate output from a command executed on -;; behalf of emacs (rather than the user). -;; - -(gdb-set-instance-buffer-rules 'gdb-partial-output-buffer - 'gdb-partial-output-name) - -(defun gdb-partial-output-name (instance) - (concat "*partial-output-" - (gdb-instance-target-string instance) - "*")) - - -(gdb-set-instance-buffer-rules 'gdb-inferior-io - 'gdb-inferior-io-name - 'gud-inferior-io-mode) - -(defun gdb-inferior-io-name (instance) - (concat "*input/output of " - (gdb-instance-target-string instance) - "*")) - -(defvar gdb-inferior-io-mode-map (copy-keymap comint-mode-map)) -(define-key gdb-inferior-io-mode-map "\C-c\C-c" 'gdb-inferior-io-interrupt) -(define-key gdb-inferior-io-mode-map "\C-c\C-z" 'gdb-inferior-io-stop) -(define-key gdb-inferior-io-mode-map "\C-c\C-\\" 'gdb-inferior-io-quit) -(define-key gdb-inferior-io-mode-map "\C-c\C-d" 'gdb-inferior-io-eof) - -(defun gud-inferior-io-mode () - "Major mode for gud inferior-io. - -\\{comint-mode-map}" - ;; We want to use comint because it has various nifty and familiar - ;; features. We don't need a process, but comint wants one, so create - ;; a dummy one. - (make-comint (substring (buffer-name) 1 (- (length (buffer-name)) 1)) - "/bin/cat") - (setq major-mode 'gud-inferior-io-mode) - (setq mode-name "Debuggee I/O") - (setq comint-input-sender 'gud-inferior-io-sender) -) - -(defun gud-inferior-io-sender (proc string) - (save-excursion - (set-buffer (process-buffer proc)) - (let ((instance gdb-buffer-instance)) - (set-buffer (gdb-get-instance-buffer instance 'gud)) - (let ((gud-proc (get-buffer-process (current-buffer)))) - (process-send-string gud-proc string) - (process-send-string gud-proc "\n") - )) - )) - -(defun gdb-inferior-io-interrupt (instance) - "Interrupt the program being debugged." - (interactive (list (gdb-needed-default-instance))) - (interrupt-process - (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp)) - -(defun gdb-inferior-io-quit (instance) - "Send quit signal to the program being debugged." - (interactive (list (gdb-needed-default-instance))) - (quit-process - (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp)) - -(defun gdb-inferior-io-stop (instance) - "Stop the program being debugged." - (interactive (list (gdb-needed-default-instance))) - (stop-process - (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp)) - -(defun gdb-inferior-io-eof (instance) - "Send end-of-file to the program being debugged." - (interactive (list (gdb-needed-default-instance))) - (process-send-eof - (get-buffer-process (gdb-get-instance-buffer instance 'gud)))) - - -;; -;; gdb communications -;; - -;; INPUT: things sent to gdb -;; -;; Each instance has a high and low priority -;; input queue. Low priority input is sent only -;; when the high priority queue is idle. -;; -;; The queues are lists. Each element is either -;; a string (indicating user or user-like input) -;; or a list of the form: -;; -;; (INPUT-STRING HANDLER-FN) -;; -;; -;; The handler function will be called from the -;; partial-output buffer when the command completes. -;; This is the way to write commands which -;; invoke gdb commands autonomously. -;; -;; These lists are consumed tail first. -;; - -(defun gdb-send (proc string) - "A comint send filter for gdb. -This filter may simply queue output for a later time." - (let ((instance (gdb-proc->instance proc))) - (gdb-instance-enqueue-input instance (concat string "\n")))) - -;; Note: Stuff enqueued here will be sent to the next prompt, even if it -;; is a query, or other non-top-level prompt. To guarantee stuff will get -;; sent to the top-level prompt, currently it must be put in the idle queue. -;; ^^^^^^^^^ -;; [This should encourage gud extentions that invoke gdb commands to let -;; the user go first; it is not a bug. -t] -;; - -(defun gdb-instance-enqueue-input (instance item) - (if (gdb-instance-prompting instance) - (progn - (gdb-send-item instance item) - (set-gdb-instance-prompting instance nil)) - (set-gdb-instance-input-queue - instance - (cons item (gdb-instance-input-queue instance))))) - -(defun gdb-instance-dequeue-input (instance) - (let ((queue (gdb-instance-input-queue instance))) - (and queue - (if (not (cdr queue)) - (let ((answer (car queue))) - (set-gdb-instance-input-queue instance '()) - answer) - (gdb-take-last-elt queue))))) - -(defun gdb-instance-enqueue-idle-input (instance item) - (if (and (gdb-instance-prompting instance) - (not (gdb-instance-input-queue instance))) - (progn - (gdb-send-item instance item) - (set-gdb-instance-prompting instance nil)) - (set-gdb-instance-idle-input-queue - instance - (cons item (gdb-instance-idle-input-queue instance))))) - -(defun gdb-instance-dequeue-idle-input (instance) - (let ((queue (gdb-instance-idle-input-queue instance))) - (and queue - (if (not (cdr queue)) - (let ((answer (car queue))) - (set-gdb-instance-idle-input-queue instance '()) - answer) - (gdb-take-last-elt queue))))) - -; Don't use this in general. -(defun gdb-take-last-elt (l) - (if (cdr (cdr l)) - (gdb-take-last-elt (cdr l)) - (let ((answer (car (cdr l)))) - (setcdr l '()) - answer))) - - -;; -;; output -- things gdb prints to emacs -;; -;; GDB output is a stream interrupted by annotations. -;; Annotations can be recognized by their beginning -;; with \C-j\C-z\C-z\C-j -;; -;; The tag is a string obeying symbol syntax. -;; -;; The optional part `' can be either the empty string -;; or a space followed by more data relating to the annotation. -;; For example, the SOURCE annotation is followed by a filename, -;; line number and various useless goo. This data must not include -;; any newlines. -;; - - -(defun gud-gdb-marker-filter (string) - "A gud marker filter for gdb." - ;; Bogons don't tell us the process except through scoping crud. - (let ((instance (gdb-proc->instance proc))) - (gdb-output-burst instance string))) - -(defvar gdb-annotation-rules - '(("frames-invalid" gdb-invalidate-frames) - ("breakpoints-invalid" gdb-invalidate-breakpoints) - ("pre-prompt" gdb-pre-prompt) - ("prompt" gdb-prompt) - ("commands" gdb-subprompt) - ("overload-choice" gdb-subprompt) - ("query" gdb-subprompt) - ("prompt-for-continue" gdb-subprompt) - ("post-prompt" gdb-post-prompt) - ("source" gdb-source) - ("starting" gdb-starting) - ("exited" gdb-stopping) - ("signalled" gdb-stopping) - ("signal" gdb-stopping) - ("breakpoint" gdb-stopping) - ("watchpoint" gdb-stopping) - ("stopped" gdb-stopped) - ("display-begin" gdb-display-begin) - ("display-end" gdb-display-end) - ("error-begin" gdb-error-begin) - ) - "An assoc mapping annotation tags to functions which process them.") - - -(defun gdb-ignore-annotation (instance args) - nil) - -(defconst gdb-source-spec-regexp - "\\(.*\\):\\([0-9]*\\):[0-9]*:[a-z]*:0x[a-f0-9]*") - -;; Do not use this except as an annotation handler." -(defun gdb-source (instance args) - (string-match gdb-source-spec-regexp args) - ;; Extract the frame position from the marker. - (setq gud-last-frame - (cons - (substring args (match-beginning 1) (match-end 1)) - (string-to-int (substring args - (match-beginning 2) - (match-end 2)))))) - -;; An annotation handler for `prompt'. -;; This sends the next command (if any) to gdb. -(defun gdb-prompt (instance ignored) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'user) t) - ((eq sink 'post-emacs) - (set-gdb-instance-output-sink instance 'user)) - (t - (set-gdb-instance-output-sink instance 'user) - (error "Phase error in gdb-prompt (got %s)" sink)))) - (let ((highest (gdb-instance-dequeue-input instance))) - (if highest - (gdb-send-item instance highest) - (let ((lowest (gdb-instance-dequeue-idle-input instance))) - (if lowest - (gdb-send-item instance lowest) - (progn - (set-gdb-instance-prompting instance t) - (gud-display-frame))))))) - -;; An annotation handler for non-top-level prompts. -(defun gdb-subprompt (instance ignored) - (let ((highest (gdb-instance-dequeue-input instance))) - (if highest - (gdb-send-item instance highest) - (set-gdb-instance-prompting instance t)))) - -(defun gdb-send-item (instance item) - (set-gdb-instance-current-item instance item) - (if (stringp item) - (progn - (set-gdb-instance-output-sink instance 'user) - (process-send-string (gdb-instance-process instance) - item)) - (progn - (gdb-clear-partial-output instance) - (set-gdb-instance-output-sink instance 'pre-emacs) - (process-send-string (gdb-instance-process instance) - (car item))))) - -;; This terminates the collection of output from a previous -;; command if that happens to be in effect. -(defun gdb-pre-prompt (instance ignored) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'user) t) - ((eq sink 'emacs) - (set-gdb-instance-output-sink instance 'post-emacs) - (let ((handler - (car (cdr (gdb-instance-current-item instance))))) - (save-excursion - (set-buffer (gdb-get-create-instance-buffer - instance 'gdb-partial-output-buffer)) - (funcall handler)))) - (t - (set-gdb-instance-output-sink instance 'user) - (error "Output sink phase error 1."))))) - -;; An annotation handler for `starting'. This says that I/O for the subprocess -;; is now the program being debugged, not GDB. -(defun gdb-starting (instance ignored) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'user) - (set-gdb-instance-output-sink instance 'inferior) - ;; FIXME: need to send queued input - ) - (t (error "Unexpected `starting' annotation"))))) - -;; An annotation handler for `exited' and other annotations which say that -;; I/O for the subprocess is now GDB, not the program being debugged. -(defun gdb-stopping (instance ignored) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'inferior) - (set-gdb-instance-output-sink instance 'user) - ) - (t (error "Unexpected stopping annotation"))))) - -;; An annotation handler for `stopped'. It is just like gdb-stopping, except -;; that if we already set the output sink to 'user in gdb-stopping, that is -;; fine. -(defun gdb-stopped (instance ignored) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'inferior) - (set-gdb-instance-output-sink instance 'user) - ) - ((eq sink 'user) - t) - (t (error "Unexpected stopping annotation"))))) - -;; An annotation handler for `post-prompt'. -;; This begins the collection of output from the current -;; command if that happens to be appropriate." -(defun gdb-post-prompt (instance ignored) - (if (not (gdb-instance-pending-triggers instance)) - (progn - (gdb-invalidate-registers instance ignored) - (gdb-invalidate-locals instance ignored) - (gdb-invalidate-display instance ignored))) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'user) t) - ((eq sink 'pre-emacs) - (set-gdb-instance-output-sink instance 'emacs)) - - (t - (set-gdb-instance-output-sink instance 'user) - (error "Output sink phase error 3."))))) - -;; Handle a burst of output from a gdb instance. -;; This function is (indirectly) used as a gud-marker-filter. -;; It must return output (if any) to be insterted in the gud -;; buffer. - -(defun gdb-output-burst (instance string) - "Handle a burst of output from a gdb instance. -This function is (indirectly) used as a gud-marker-filter. -It must return output (if any) to be insterted in the gud -buffer." - - (save-match-data - (let ( - ;; Recall the left over burst from last time - (burst (concat (gdb-instance-burst instance) string)) - ;; Start accumulating output for the gud buffer - (output "")) - - ;; Process all the complete markers in this chunk. - - (while (string-match "\n\032\032\\(.*\\)\n" burst) - (let ((annotation (substring burst - (match-beginning 1) - (match-end 1)))) - - ;; Stuff prior to the match is just ordinary output. - ;; It is either concatenated to OUTPUT or directed - ;; elsewhere. - (setq output - (gdb-concat-output - instance - output - (substring burst 0 (match-beginning 0)))) - - ;; Take that stuff off the burst. - (setq burst (substring burst (match-end 0))) - - ;; Parse the tag from the annotation, and maybe its arguments. - (string-match "\\(\\S-*\\) ?\\(.*\\)" annotation) - (let* ((annotation-type (substring annotation - (match-beginning 1) - (match-end 1))) - (annotation-arguments (substring annotation - (match-beginning 2) - (match-end 2))) - (annotation-rule (assoc annotation-type - gdb-annotation-rules))) - ;; Call the handler for this annotation. - (if annotation-rule - (funcall (car (cdr annotation-rule)) - instance - annotation-arguments) - ;; Else the annotation is not recognized. Ignore it silently, - ;; so that GDB can add new annotations without causing - ;; us to blow up. - )))) - - - ;; Does the remaining text end in a partial line? - ;; If it does, then keep part of the burst until we get more. - (if (string-match "\n\\'\\|\n\032\\'\\|\n\032\032.*\\'" - burst) - (progn - ;; Everything before the potential marker start can be output. - (setq output - (gdb-concat-output - instance - output - (substring burst 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq burst (substring burst (match-beginning 0)))) - - ;; In case we know the burst contains no partial annotations: - (progn - (setq output (gdb-concat-output instance output burst)) - (setq burst ""))) - - ;; Save the remaining burst for the next call to this function. - (set-gdb-instance-burst instance burst) - output))) - -(defun gdb-concat-output (instance so-far new) - (let ((sink (gdb-instance-output-sink instance))) - (cond - ((eq sink 'user) (concat so-far new)) - ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far) - ((eq sink 'emacs) - (gdb-append-to-partial-output instance new) - so-far) - ((eq sink 'inferior) - (gdb-append-to-inferior-io instance new) - so-far) - (t (error "Bogon output sink %S" sink))))) - -(defun gdb-append-to-partial-output (instance string) - (save-excursion - (buffer-disable-undo ; Don't need undo in partial output buffer - (set-buffer - (gdb-get-create-instance-buffer - instance 'gdb-partial-output-buffer))) - (goto-char (point-max)) - (insert string))) - -(defun gdb-clear-partial-output (instance) - (save-excursion - (set-buffer - (gdb-get-create-instance-buffer - instance 'gdb-partial-output-buffer)) - (delete-region (point-min) (point-max)))) - -(defun gdb-append-to-inferior-io (instance string) - (save-excursion - (set-buffer - (gdb-get-create-instance-buffer - instance 'gdb-inferior-io)) - (goto-char (point-max)) - (insert-before-markers string)) - (gud-display-buffer - (gdb-get-create-instance-buffer instance - 'gdb-inferior-io))) - -(defun gdb-clear-inferior-io (instance) - (save-excursion - (set-buffer - (gdb-get-create-instance-buffer - instance 'gdb-inferior-io)) - (delete-region (point-min) (point-max)))) - - - -;; One trick is to have a command who's output is always available in -;; a buffer of it's own, and is always up to date. We build several -;; buffers of this type. -;; -;; There are two aspects to this: gdb has to tell us when the output -;; for that command might have changed, and we have to be able to run -;; the command behind the user's back. -;; -;; The idle input queue and the output phasing associated with -;; the instance variable `(gdb-instance-output-sink instance)' help -;; us to run commands behind the user's back. -;; -;; Below is the code for specificly managing buffers of output from one -;; command. -;; - - -;; The trigger function is suitable for use in the assoc GDB-ANNOTATION-RULES -;; It adds an idle input for the command we are tracking. It should be the -;; annotation rule binding of whatever gdb sends to tell us this command -;; might have changed it's output. -;; -;; NAME is the function name. DEMAND-PREDICATE tests if output is really needed. -;; GDB-COMMAND is a string of such. OUTPUT-HANDLER is the function bound to the -;; input in the input queue (see comment about ``gdb communications'' above). -(defmacro def-gdb-auto-update-trigger (name demand-predicate gdb-command output-handler) - (` - (defun (, name) (instance &optional ignored) - (if (and ((, demand-predicate) instance) - (not (member '(, name) - (gdb-instance-pending-triggers instance)))) - (progn - (gdb-instance-enqueue-idle-input - instance - (list (, gdb-command) '(, output-handler))) - (set-gdb-instance-pending-triggers - instance - (cons '(, name) - (gdb-instance-pending-triggers instance)))) )))) - -(defmacro def-gdb-auto-update-handler (name trigger buf-key) - (` - (defun (, name) () - (set-gdb-instance-pending-triggers - instance - (delq '(, trigger) - (gdb-instance-pending-triggers instance))) - (let ((buf (gdb-get-instance-buffer instance - '(, buf-key)))) - (and buf - (save-excursion - (set-buffer buf) - (buffer-disable-undo buf) ; don't need undo - (let ((p (point)) - (buffer-read-only nil) - (instance-buf (gdb-get-create-instance-buffer - instance - 'gdb-partial-output-buffer))) - (if (gud-buffers-differ buf instance-buf) - (progn - (delete-region (point-min) (point-max)) - (insert-buffer instance-buf) - (if (buffer-dedicated-frame) - (fit-frame-to-buffer (buffer-dedicated-frame) buf)) - )) - (goto-char p)))))))) - -(defmacro def-gdb-auto-updated-buffer - (buffer-key trigger-name gdb-command output-handler-name) - (` - (progn - (def-gdb-auto-update-trigger (, trigger-name) - ;; The demand predicate: - (lambda (instance) - (gdb-get-instance-buffer instance '(, buffer-key))) - (, gdb-command) - (, output-handler-name)) - (def-gdb-auto-update-handler (, output-handler-name) - (, trigger-name) (, buffer-key))))) - - -;; -;; Breakpoint buffers -;; -;; These display the output of `info breakpoints'. -;; - - -(gdb-set-instance-buffer-rules 'gdb-breakpoints-buffer - 'gdb-breakpoints-buffer-name - 'gud-breakpoints-mode) - -(def-gdb-auto-updated-buffer gdb-breakpoints-buffer - ;; This defines the auto update rule for buffers of type - ;; `gdb-breakpoints-buffer'. - ;; - ;; It defines a function to serve as the annotation handler that - ;; handles the `foo-invalidated' message. That function is called: - gdb-invalidate-breakpoints - - ;; To update the buffer, this command is sent to gdb. - "server info breakpoints\n" - - ;; This also defines a function to be the handler for the output - ;; from the command above. That function will copy the output into - ;; the appropriately typed buffer. That function will be called: - gdb-info-breakpoints-handler) - -(defun gdb-breakpoints-buffer-name (instance) - (save-excursion - (set-buffer (process-buffer (gdb-instance-process instance))) - (concat "*breakpoints of " (gdb-instance-target-string instance) "*"))) - -(defun gud-display-breakpoints-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer - (gdb-get-create-instance-buffer instance - 'gdb-breakpoints-buffer))) - -(defun gud-frame-breakpoints-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer-new-frame - (gdb-get-create-instance-buffer instance - 'gdb-breakpoints-buffer))) - -(defvar gud-breakpoints-mode-map nil) -(defvar gud-breakpoints-mode-menu - '("GDB Breakpoint Commands" - "----" - ["Toggle" gud-toggle-bp-this-line t] - ["Delete" gud-delete-bp-this-line t] - ["Condition" gud-bp-condition t] - ["Ignore" gud-bp-ignore t]) - "*menu for gud-breakpoints-mode") - -(setq gud-breakpoints-mode-map (make-keymap)) -(suppress-keymap gud-breakpoints-mode-map) -(define-key gud-breakpoints-mode-map " " 'gud-toggle-bp-this-line) -(define-key gud-breakpoints-mode-map "d" 'gud-delete-bp-this-line) -(define-key gud-breakpoints-mode-map "c" 'gud-bp-condition) -(define-key gud-breakpoints-mode-map "i" 'gud-bp-ignore) -(define-key gud-breakpoints-mode-map 'button3 'gud-breakpoints-popup-menu) -(defun gud-breakpoints-mode () - "Major mode for gud breakpoints. - -\\{gud-breakpoints-mode-map}" - (setq major-mode 'gud-breakpoints-mode) - (setq mode-name "Breakpoints") - (use-local-map gud-breakpoints-mode-map) - (setq buffer-read-only t) - (require 'mode-motion) - (setq mode-motion-hook 'gud-breakpoints-mode-motion-hook) - (gdb-invalidate-breakpoints gdb-buffer-instance)) - -(defun gud-toggle-bp-this-line () - (interactive) - (save-excursion - (set-buffer - (gdb-get-instance-buffer gdb-buffer-instance 'gdb-breakpoints-buffer)) - (if (key-press-event-p last-input-event) - (beginning-of-line 1) - (and mode-motion-extent (extent-buffer mode-motion-extent) - (goto-char (extent-start-position mode-motion-extent)))) - (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)")) - (error "Not recognized as breakpoint line (demo foo).") - (gdb-instance-enqueue-idle-input - gdb-buffer-instance - (list - (concat - (if (eq ?y (char-after (match-beginning 2))) - "server disable " - "server enable ") - (buffer-substring (match-beginning 0) - (match-end 1)) - "\n") - '(lambda () nil))) - ))) - -(defun gud-delete-bp-this-line () - (interactive) - (save-excursion - (set-buffer - (gdb-get-instance-buffer gdb-buffer-instance 'gdb-breakpoints-buffer)) - (if (key-press-event-p last-input-event) - (beginning-of-line 1) - (and mode-motion-extent (extent-buffer mode-motion-extent) - (goto-char (extent-start-position mode-motion-extent)))) - (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)")) - (error "Not recognized as breakpoint line (demo foo).") - (gdb-instance-enqueue-idle-input - gdb-buffer-instance - (list - (concat - "server delete " - (buffer-substring (match-beginning 0) - (match-end 1)) - "\n") - '(lambda () nil))) - ))) - -(defun gud-bp-condition (condition) - (interactive "sCondition for breakpoint: ") - (save-excursion - (set-buffer - (gdb-get-instance-buffer gdb-buffer-instance 'gdb-breakpoints-buffer)) - (if (key-press-event-p last-input-event) - (beginning-of-line 1) - (and mode-motion-extent (extent-buffer mode-motion-extent) - (goto-char (extent-start-position mode-motion-extent)))) - (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)")) - (error "Not recognized as breakpoint line (demo foo).") - (gdb-instance-enqueue-idle-input - gdb-buffer-instance - (list - (concat - "server condition " - (buffer-substring (match-beginning 0) - (match-end 1)) - (if (> (length condition) 0) (concat " " condition) "") - "\n") - '(lambda () nil))) - (gdb-invalidate-breakpoints gdb-buffer-instance) - ))) - -(defun gud-bp-ignore (count) - (interactive "nNumber of times to ignore breakpoint: ") - (save-excursion - (set-buffer - (gdb-get-instance-buffer gdb-buffer-instance 'gdb-breakpoints-buffer)) - (if (key-press-event-p last-input-event) - (beginning-of-line 1) - (and mode-motion-extent (extent-buffer mode-motion-extent) - (goto-char (extent-start-position mode-motion-extent)))) - (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)")) - (error "Not recognized as breakpoint line (demo foo).") - (gdb-instance-enqueue-idle-input - gdb-buffer-instance - (list - (concat - "server ignore " - (buffer-substring (match-beginning 0) - (match-end 1)) - " " - (int-to-string count) - "\n") - '(lambda () nil))) - (gdb-invalidate-breakpoints gdb-buffer-instance) - ))) - -(defun gud-breakpoints-mode-motion-hook (event) - (gud-breakpoints-mode-motion-internal event "^[0-9]+[ \t]")) - -(defun gud-breakpoints-mode-motion-internal (event regexp) - ;; - ;; This is mostly ripped off from mode-motion-highlight-internal but - ;; we set the extent's face rather than setting it to highlight. That - ;; way if we're somewhere in the breakpoint's list of commands or other - ;; info we still highlight it. - (if (event-buffer event) - (let* ((buffer (event-buffer event)) - point) - (save-excursion - (set-buffer buffer) - (mouse-set-point event) - (beginning-of-line) - (if (not (looking-at regexp)) - (re-search-backward regexp (point-min) 't)) - (setq point (point)) - (if (looking-at regexp) - (end-of-line)) - (if (and mode-motion-extent (extent-buffer mode-motion-extent)) - (if (eq point (point)) - (delete-extent mode-motion-extent) - (set-extent-endpoints mode-motion-extent point (point))) - (if (eq point (point)) - nil - (setq mode-motion-extent (make-extent point (point))) - (set-extent-property mode-motion-extent 'face - (get-face 'highlight))))) - ))) - -(defun gud-breakpoints-popup-menu (event) - (interactive "@e") - (mouse-set-point event) - (popup-menu gud-breakpoints-mode-menu)) - -;; -;; Display expression buffers -;; -;; These show the current list of expressions which the debugger -;; prints when the inferior stops and their values. Note that there -;; isn't a "display-invalid" annotation so we have to a bit more -;; work than for the other auto-update buffers -;; - -(gdb-set-instance-buffer-rules 'gdb-display-buffer - 'gdb-display-buffer-name - 'gud-display-mode) - - -(def-gdb-auto-updated-buffer gdb-display-buffer - ;; This defines the auto update rule for buffers of type - ;; `gdb-display-buffer'. - ;; - ;; It defines a function to serve as the annotation handler that - ;; handles the `foo-invalidated' message. That function is called: - gdb-invalidate-display - - ;; To update the buffer, this command is sent to gdb. - "server info display\n" - - ;; This also defines a function to be the handler for the output - ;; from the command above. That function will copy the output into - ;; the appropriately typed buffer. That function will be called: - gdb-info-display-handler) - - -;; Since the displayed expressions buffer is not simply a copy of what gdb -;; prints for the "info display" command we need a slightly more complex -;; handler for it than the standard one which def-gdb-auto-updated-buffer -;; defines. - -(defun gdb-info-display-handler () - - (set-gdb-instance-pending-triggers - instance (delq 'gdb-invalidate-display - (gdb-instance-pending-triggers instance))) - - (let ((buf (gdb-get-instance-buffer instance 'gdb-display-buffer))) - (and buf - (save-excursion - (let ((instance-buf (gdb-get-create-instance-buffer - instance 'gdb-partial-output-buffer)) - expr-alist point expr highlight-expr) - (set-buffer instance-buf) - (goto-char (point-min)) - (while - (re-search-forward "^\\([0-9]+\\): \\([ny] .*$\\)" (point-max) t) - (setq expr-alist - (cons - (cons (buffer-substring (match-beginning 1) (match-end 1)) - (buffer-substring (match-beginning 2) (match-end 2))) - expr-alist))) - (set-buffer buf) - (setq buffer-read-only nil) - (if (and mode-motion-extent - (extent-buffer mode-motion-extent) - (extent-start-position mode-motion-extent)) - (progn - (goto-char (extent-start-position mode-motion-extent)) - (if (looking-at "^[0-9]+:") - (setq highlight-expr (buffer-substring (match-beginning 0) (match-end 0)))))) - (goto-char (point-min)) - (delete-region (point-min) - (if (not (re-search-forward "^\\([0-9]+\\): " (point-max) t)) - (point-max) - (beginning-of-line) - (point))) - (if (not expr-alist) - (progn - (insert "There are no auto-display expressions now.\n") - (delete-region (point) (point-max))) - (insert "Auto-display expressions now in effect: -Num Enb Expression = value\n") - (while - (re-search-forward "^\\([0-9]+\\): \\([ny]\\)" (point-max) t) - (if (setq expr (assoc (buffer-substring (match-beginning 1) (match-end 1)) - expr-alist)) - (progn - (if (string-equal (substring (cdr expr) 0 1) "y") - (replace-match "\\1: y") - (replace-match (format "\\1: %s" (cdr expr))) - (setq point (point)) - (if (re-search-forward "^[0-9]+: " (point-max) 'move) - (beginning-of-line)) - (delete-region point (if (eobp) (point) (1- (point))))) - (setq expr-alist (delq expr expr-alist))) - (beginning-of-line) - (setq point (point)) - (if (re-search-forward "^[0-9]+: " (point-max) 'move 2) - (beginning-of-line)) - (delete-region point (point)))) - (goto-char (point-max)) - (while expr-alist - (insert (concat (car (car expr-alist)) ": " - (cdr (car expr-alist)) "\n" )) - (setq expr-alist (cdr expr-alist))) ) - (goto-char (point-min)) - (if (and mode-motion-extent - (extent-buffer mode-motion-extent) - highlight-expr - (re-search-forward (concat "^" highlight-expr ".*$") (point-max) t)) - (set-extent-endpoints mode-motion-extent (match-beginning 0) (match-end 0))) - (setq buffer-read-only t) - (if (buffer-dedicated-frame) - (fit-frame-to-buffer (buffer-dedicated-frame) buf)) - ))))) - -(defvar gud-display-mode-map nil) -(setq gud-display-mode-map (make-keymap)) -(suppress-keymap gud-display-mode-map) - -(defvar gud-display-mode-menu - '("GDB Display Commands" - "----" - ["Toggle enable" gud-toggle-disp-this-line t] - ["Delete" gud-delete-disp-this-line t]) - "*menu for gud-display-mode") - -(define-key gud-display-mode-map " " 'gud-toggle-disp-this-line) -(define-key gud-display-mode-map "d" 'gud-delete-disp-this-line) -(define-key gud-display-mode-map 'button3 'gud-display-popup-menu) - -(defun gud-display-mode () - "Major mode for gud display. - -\\{gud-display-mode-map}" - (setq major-mode 'gud-display-mode) - (setq mode-name "Display") - (setq buffer-read-only t) - (use-local-map gud-display-mode-map) - (require 'mode-motion) - (setq mode-motion-hook 'gud-display-mode-motion-hook) - (gdb-invalidate-display gdb-buffer-instance) - ) - -(defun gdb-display-buffer-name (instance) - (save-excursion - (set-buffer (process-buffer (gdb-instance-process instance))) - (concat "*Displayed expressions of " (gdb-instance-target-string instance) "*"))) - -(defun gud-display-display-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (let ((buf (gdb-get-create-instance-buffer instance - 'gdb-display-buffer))) - (gdb-invalidate-display instance) - (gud-display-buffer buf))) - - -(defun gud-frame-display-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (let ((buf (gdb-get-create-instance-buffer instance - 'gdb-display-buffer))) - (gdb-invalidate-display instance) - (gud-display-buffer-new-frame buf))) - -(defun gud-toggle-disp-this-line () - (interactive) - (save-excursion - (set-buffer - (gdb-get-instance-buffer gdb-buffer-instance 'gdb-display-buffer)) - (if (key-press-event-p last-input-event) - (beginning-of-line 1) - (and mode-motion-extent (extent-buffer mode-motion-extent) - (goto-char (extent-start-position mode-motion-extent)))) - (if (not (looking-at "\\([0-9]+\\): \\([ny]\\)")) - (error "No expression on this line.") - (gdb-instance-enqueue-idle-input - gdb-buffer-instance - (list - (concat - (if (eq ?y (char-after (match-beginning 2))) - "server disable display " - "server enable display ") - (buffer-substring (match-beginning 0) - (match-end 1)) - "\n") - '(lambda () nil))) - ))) - -(defun gud-delete-disp-this-line () - (interactive) - (save-excursion - (set-buffer - (gdb-get-instance-buffer gdb-buffer-instance 'gdb-display-buffer)) - (if (key-press-event-p last-input-event) - (beginning-of-line 1) - (and mode-motion-extent (extent-buffer mode-motion-extent) - (goto-char (extent-start-position mode-motion-extent)))) - (if (not (looking-at "\\([0-9]+\\): \\([ny]\\)")) - (error "No expression on this line.") - (gdb-instance-enqueue-idle-input - gdb-buffer-instance - (list - (concat - "server delete display " - (buffer-substring (match-beginning 0) - (match-end 1)) - "\n") - '(lambda () nil))) - ))) - -(defun gud-display-mode-motion-hook (event) - (gud-breakpoints-mode-motion-internal event "^[0-9]+: ")) - -(defun gud-display-popup-menu (event) - (interactive "@e") - (mouse-set-point event) - (popup-menu gud-display-mode-menu)) - -;; If we get an error whilst evaluating one of the expressions -;; we won't get the display-end annotation. Set the sink back to -;; user to make sure that the error message is seen - -(defun gdb-error-begin (instance ignored) - (set-gdb-instance-output-sink instance 'user)) - -(defun gdb-display-begin (instance ignored) - (if (gdb-get-instance-buffer instance 'gdb-display-buffer) - (progn - (set-gdb-instance-output-sink instance 'emacs) - (gdb-clear-partial-output instance)) - (set-gdb-instance-output-sink instance 'user)) - ) - -(defun gdb-display-end (instance ignored) - (save-excursion - (let ((display-output (gdb-get-instance-buffer instance 'gdb-display-buffer)) - display-index - display-value - highlight-expr) - (if display-output - (progn - (set-buffer (gdb-get-instance-buffer - instance 'gdb-partial-output-buffer)) - (goto-char (point-min)) - (looking-at "\\([0-9]+\\): ") - (setq display-index (buffer-substring (match-beginning 1) - (match-end 1))) - (setq display-value (+ 2 (match-end 1))) - (set-buffer display-output) - (if (and mode-motion-extent - (extent-buffer mode-motion-extent) - (extent-start-position mode-motion-extent)) - (progn - (goto-char (extent-start-position mode-motion-extent)) - (if (looking-at "^[0-9]+:") - (setq highlight-expr (buffer-substring (match-beginning 0) (match-end 0)))))) - (setq buffer-read-only nil) - (goto-char (point-min)) - (if (not (re-search-forward (concat "^" display-index ": [ny] ") - (point-max) 'move)) - (insert (format "%s: y " display-index)) - (goto-char (match-end 0)) - (if (save-match-data - (re-search-forward "^[0-9]+: " (point-max) 'move)) - (beginning-of-line)) - (delete-region (match-end 0) (point))) - (insert-buffer-substring (gdb-get-instance-buffer - instance 'gdb-partial-output-buffer) - display-value) - (goto-char (point-min)) - (if (and mode-motion-extent - (extent-buffer mode-motion-extent) - highlight-expr - (re-search-forward (concat "^" highlight-expr ".*$") (point-max) t)) - (set-extent-endpoints mode-motion-extent (match-beginning 0) (match-end 0))) - (setq buffer-read-only t) - ))) - (gdb-clear-partial-output instance) - (set-gdb-instance-output-sink instance 'user) - )) - - -;; -;; Frames buffers. These display a perpetually correct bactracktrace -;; (from the command `where'). -;; -;; Alas, if your stack is deep, they are costly. -;; - -(gdb-set-instance-buffer-rules 'gdb-stack-buffer - 'gdb-stack-buffer-name - 'gud-frames-mode) - -(def-gdb-auto-updated-buffer gdb-stack-buffer - gdb-invalidate-frames - "server where\n" - gdb-info-frames-handler) - -(defun gdb-stack-buffer-name (instance) - (save-excursion - (set-buffer (process-buffer (gdb-instance-process instance))) - (concat "*stack frames of " - (gdb-instance-target-string instance) "*"))) - -(defun gud-display-stack-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer - (gdb-get-create-instance-buffer instance - 'gdb-stack-buffer))) - -(defun gud-frame-stack-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer-new-frame - (gdb-get-create-instance-buffer instance - 'gdb-stack-buffer))) - -(defvar gud-frames-mode-map nil) -(setq gud-frames-mode-map (make-keymap)) -(suppress-keymap gud-frames-mode-map) - -;;; XEmacs change -;(define-key gud-frames-mode-map [mouse-2] -; 'gud-frames-select-by-mouse) - -(define-key gud-frames-mode-map [button2] - 'gud-frames-select-by-mouse) - - -(defun gud-frames-mode () - "Major mode for gud frames. - -\\{gud-frames-mode-map}" - (setq major-mode 'gud-frames-mode) - (setq mode-name "Frames") - (setq buffer-read-only t) - (use-local-map gud-frames-mode-map) - (gdb-invalidate-frames gdb-buffer-instance)) - -(defun gud-get-frame-number () - (save-excursion - (let* ((pos (re-search-backward "^#\\([0-9]*\\)" nil t)) - (n (or (and pos - (string-to-int - (buffer-substring (match-beginning 1) - (match-end 1)))) - 0))) - n))) - -(defun gud-frames-select-by-mouse (e) - (interactive "e") - (let (selection) - (save-excursion - (set-buffer (window-buffer (posn-window (event-end e)))) - (save-excursion - (goto-char (posn-point (event-end e))) - (setq selection (gud-get-frame-number)))) - (select-window (posn-window (event-end e))) - (save-excursion - (set-buffer (gdb-get-instance-buffer (gdb-needed-default-instance) 'gud)) - (gud-call "fr %p" selection) - (gud-display-frame)))) - - -;; -;; Registers buffers -;; - -(def-gdb-auto-updated-buffer gdb-registers-buffer - gdb-invalidate-registers - "server info registers\n" - gdb-info-registers-handler) - -(gdb-set-instance-buffer-rules 'gdb-registers-buffer - 'gdb-registers-buffer-name - 'gud-registers-mode) - -(defvar gud-registers-mode-map nil) -(setq gud-registers-mode-map (make-keymap)) -(suppress-keymap gud-registers-mode-map) - -(defun gud-registers-mode () - "Major mode for gud registers. - -\\{gud-registers-mode-map}" - (setq major-mode 'gud-registers-mode) - (setq mode-name "Registers") - (setq buffer-read-only t) - (use-local-map gud-registers-mode-map) - (gdb-invalidate-registers gdb-buffer-instance)) - -(defun gdb-registers-buffer-name (instance) - (save-excursion - (set-buffer (process-buffer (gdb-instance-process instance))) - (concat "*registers of " (gdb-instance-target-string instance) "*"))) - -(defun gud-display-registers-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer - (gdb-get-create-instance-buffer instance - 'gdb-registers-buffer))) - -(defun gud-frame-registers-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer-new-frame - (gdb-get-create-instance-buffer instance - 'gdb-registers-buffer))) - -;; -;; Locals buffers -;; - -(def-gdb-auto-updated-buffer gdb-locals-buffer - gdb-invalidate-locals - "server info locals\n" - gdb-info-locals-handler) - -(gdb-set-instance-buffer-rules 'gdb-locals-buffer - 'gdb-locals-buffer-name - 'gud-locals-mode) - -(defvar gud-locals-mode-map nil) -(setq gud-locals-mode-map (make-keymap)) -(suppress-keymap gud-locals-mode-map) - -(defun gud-locals-mode () - "Major mode for gud locals. - -\\{gud-locals-mode-map}" - (setq major-mode 'gud-locals-mode) - (setq mode-name "Locals") - (setq buffer-read-only t) - (use-local-map gud-locals-mode-map) - (gdb-invalidate-locals gdb-buffer-instance)) - -(defun gdb-locals-buffer-name (instance) - (save-excursion - (set-buffer (process-buffer (gdb-instance-process instance))) - (concat "*locals of " (gdb-instance-target-string instance) "*"))) - -(defun gud-display-locals-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer - (gdb-get-create-instance-buffer instance - 'gdb-locals-buffer))) - -(defun gud-frame-locals-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer-new-frame - (gdb-get-create-instance-buffer instance - 'gdb-locals-buffer))) - - -;;;; -;;;; Put a friendly face on the GDB on-line help. -;;;; - -;; Keymap for extents in the help buffer -(setq gdb-help-extent-map (make-keymap)) -(suppress-keymap gdb-help-extent-map) -(define-key gdb-help-extent-map 'button2 'gdb-help-xref) -(define-key gdb-help-extent-map 'button3 'gdb-help-popup-menu) - -;; Keymap for elsewhere in the help buffer -(setq gdb-help-map (make-keymap)) -(define-key gdb-help-map 'button3 'gdb-help-popup-menu) - -(defvar gud-help-menu - '("GDB Help Topics" - "----" - ("Classes of GDB Commands" - "----" - ["running" (gdb-help "running") t] - ["stack" (gdb-help "stack") t] - ["data" (gdb-help "data") t] - ["breakpoints" (gdb-help "breakpoints") t] - ["files" (gdb-help "files") t] - ["status" (gdb-help "status") t] - ["support" (gdb-help "support") t] - ["user-defined" (gdb-help "user-defined") t] - ["aliases" (gdb-help "aliases") t] - ["obscure" (gdb-help "obscure") t] - ["internals" (gdb-help "internals") t]) - "----" - ("Prefix Commands" - "----" - ["info" (gdb-help "info") t] - ["delete" (gdb-help "delete") t] - ["disable" (gdb-help "disable") t] - ["enable" (gdb-help "enable") t] - ["maintenance" (gdb-help "maintenance") t] - ["maintenance info" (gdb-help "maintenance info") t] - ["maintenance print" (gdb-help "maintenance print") t] - ["show" (gdb-help "show") t] - ["show check" (gdb-help "show check") t] - ["show history" (gdb-help "show history") t] - ["show print" (gdb-help "show print") t] - ["set" (gdb-help "set") t] - ["set check" (gdb-help "set check") t] - ["set history" (gdb-help "set history") t] - ["set print" (gdb-help "set print") t] - ["thread" (gdb-help "thread") t] - ["thread apply" (gdb-help "thread apply") t] - ["unset" (gdb-help "unset") t]) -; Only if you build this into gdb -; ("Duel" -; ["summary" (gdb-help "duel help") t] -; ["ops" (gdb-help "duel ops") t] -; ["examples" (gdb-help "duel examples") t]) - ) - "*menu for gdb-help") - -(defun gdb-help-popup-menu (event) - (interactive "@e") - (mouse-set-point event) - (popup-menu gud-help-menu)) - -(defun gdb-help-xref (event) - (interactive "e") - (save-excursion - (set-buffer (get-buffer (gettext "*Debugger Help*"))) - (let ((extent (extent-at (event-point event)))) - (gdb-help - (or (extent-property extent 'back-to) - (buffer-substring (extent-start-position extent) - (extent-end-position extent))) - gdb-help-topic) - ))) - -(defun gdb-help-info () - (interactive) - (require 'info) - (Info-goto-node "(gdb)Top")) - -;; Format the help page. We lightly edit the GDB output to add instructions -;; on getting help on listed commands using the mouse rather than typing -;; "help" at gdb. -;; -;; We're not trying to re-produce Info's or w3's navigational and cross -;; referencing here but just to put a simple mouse-driven front end over -;; GDB's help. -;; -;; The help buffer *ought* to be in gdb-help-mode but we only ever create -;; one buffer so just setting a buffer local keymap should be good enough -;; for now. - -(defun gdb-format-help-page nil - (save-excursion - (display-buffer (set-buffer (get-buffer-create - (gettext "*Debugger Help*")))) - (erase-buffer) - (map-extents '(lambda (extent) (delete-extent extent) nil)) - (use-local-map gdb-help-map) - (insert-buffer (gdb-get-instance-buffer - instance 'gdb-partial-output-buffer)) - (goto-char (point-min)) - (forward-line 1) - (while (re-search-forward "\\(^.*\\) -- .*$" (point-max) t) - (let ((extent (make-extent (match-beginning 1) (match-end 1)))) - (set-extent-property extent 'face (find-face 'bold)) - (set-extent-property extent 'highlight t) - (set-extent-property extent 'keymap gdb-help-extent-map) - )) - ;; We use the message at the end of the help to distinguish between - ;; help on a class of commands, help on a prefix command and help - ;; on a command. - (goto-char (point-min)) - (cond - ((looking-at "List of classes of commands:") - ;; It's the list of classes - (end-of-line) - (insert " Click on a highlighted class to see the list of commands -in that class.") - ) - ((and (not (looking-at "List of classes of commands:")) - (re-search-forward "^Type \"help\" followed by command name" (point-max) t)) - ;; It's help on a specific class - (goto-char (point-min)) - (insert "Help on ") - (downcase-word 1) - (end-of-line) - (insert " Click on a highlighted command to see the help -for that command or click ") - (setq point (point)) - (insert "here") - (setq extent (make-extent point (point))) - (set-extent-property extent 'back-to "") - (insert " to see the list of classes of commands.\n") - ) - ((re-search-forward "^Type \"help.*subcommand" (point-max) t) - ;; It's a prefix command - (goto-char (point-min)) - (insert (concat "Help on \"" gdb-help-topic "\" - ")) - (downcase-word 1) - (end-of-line) - (insert " Click on a highlighted topic to see the help -for that topic or click ") - (setq point (point)) - (insert "here") - (setq extent (make-extent point (point))) - (string-match " ?[^ \t]*$" gdb-help-topic) - (if (equal "" - (set-extent-property extent 'back-to - (substring gdb-help-topic - 0 (match-beginning 0)))) - (insert " to see the list of classes of commands.\n") - (insert (concat " to see the help on " (extent-property extent 'back-to )))) - ) - (t - ;; Must be an ordinary command - (goto-char (point-min)) - (insert (concat "Help on \"" gdb-help-topic "\" - ")) - (insert " Click ") - (setq point (point)) - (insert "here") - (setq extent (make-extent point (point))) - (if (equal "" (set-extent-property extent 'back-to gdb-previous-help-topic)) - (insert " to see the list of classes of commands.\n") - (insert (concat " to see the help on " (extent-property extent 'back-to )))) - ) - ) - (and extent - (set-extent-property extent 'face (find-face 'bold)) - (set-extent-property extent 'highlight t) - (set-extent-property extent 'keymap gdb-help-extent-map)) - (setq fill-column 78) - (fill-region (point-min) (point)) - (insert "\n") - )) - -(defun gdb-help (topic &optional previous-topic) - (interactive "sGdb Help Topic: ") - (let ((instance (gdb-needed-default-instance)) - ) - (save-excursion - (set-buffer (get-buffer-create (gettext "*Debugger Help*"))) - (make-variable-buffer-local 'gdb-help-topic) - (make-variable-buffer-local 'gdb-previous-help-topic) - (setq gdb-help-topic topic) - (setq gdb-previous-help-topic (or previous-topic ""))) - (gdb-clear-partial-output instance) - (gdb-instance-enqueue-idle-input - instance - (list - (concat - "server " - (if (string-match "^duel" topic) - "" - "help ") - topic - "\n") - 'gdb-format-help-page)))) - -;;;; Menus and stuff - -(defun gdb-install-menubar () - "Installs the Gdb menu at the menubar." - - ;; We can't define the menu at load-time because many of the functions - ;; that we will call won't be bound then. - (defvar gdb-menu - '("GDB Commands" - "----" - ("Help" - ["info" gdb-help-info t] - "----" - ["running -- Running the program" (gdb-help "running") t] - ["stack -- Examining the stack" (gdb-help "stack") t] - ["data -- Examining data" (gdb-help "data") t] - ["breakpoints -- Making program stop at certain points" (gdb-help "breakpoints") t] - ["files -- Specifying and examining files" (gdb-help "files") t] - ["status -- Status inquiries" (gdb-help "status") t] - ["support -- Support facilities" (gdb-help "support") t] - ["user-defined -- User-defined commands" (gdb-help "user-defined") t] - ["aliases -- Aliases of other commands" (gdb-help "aliases") t] - ["obscure -- Obscure features" (gdb-help "obscure") t] - ["internals -- Maintenance commands" (gdb-help "internals") t] - "---" -; Only if you build this into gdb -; ["Duel summary" (gdb-help "duel help") t] -; ["Duel ops" (gdb-help "duel ops") t] -; ["Duel examples" (gdb-help "duel examples") t] - ) - "---" - ("New window showing" - ["Local variables" gud-display-locals-buffer t] - ["Displayed expressions" gud-display-display-buffer t] - ["Breakpoints" gud-display-breakpoints-buffer t] - ["Stack trace" gud-display-stack-buffer t] - ["Machine registers" gud-display-registers-buffer t] - ) - ("New frame showing" - ["Local variables" gud-frame-locals-buffer t] - ["Displayed expressions" gud-frame-display-buffer t] - ["Breakpoints" gud-frame-breakpoints-buffer t] - ["Stack trace" gud-frame-stack-buffer t] - ["Machine registers" gud-frame-registers-buffer t] - ) - "----" - ["step" gud-step t] - ["next" gud-next t] - ["finish" gud-finish t] - ["continue" gud-cont t] - ["run" gud-run t] - ) - "*The menu for GDB mode.") - (if (and current-menubar (not (assoc "Gdb" current-menubar))) - (progn - (set-buffer-menubar (copy-sequence current-menubar)) - (add-menu nil "Gdb" (cdr gdb-menu)))) - ) -(add-hook 'gdb-mode-hook 'gdb-install-menubar) - - -(gdb-set-instance-buffer-rules 'gdb-command-buffer - 'gdb-command-buffer-name - 'gud-command-mode) - -(defvar gud-command-mode-map nil) -(setq gud-command-mode-map (make-keymap)) -(suppress-keymap gud-command-mode-map) -;;; XEmacs change -;(define-key gud-command-mode-map [mouse-2] 'gud-menu-pick) -(define-key gud-command-mode-map [button2] 'gud-menu-pick) - - -(defun gud-command-mode () - "Major mode for gud menu. - -\\{gud-command-mode-map}" (interactive) (setq major-mode 'gud-command-mode) - (setq mode-name "Menu") (setq buffer-read-only t) (use-local-map - gud-command-mode-map) (make-variable-buffer-local 'gud-menu-position) - (if (not gud-menu-position) (gud-goto-menu gud-running-menu))) - -(defun gdb-command-buffer-name (instance) - (save-excursion - (set-buffer (process-buffer (gdb-instance-process instance))) - (concat "*menu of " (gdb-instance-target-string instance) "*"))) - -(defun gud-display-command-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer - (gdb-get-create-instance-buffer instance - 'gdb-command-buffer) - 6)) - -(defun gud-frame-command-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer-new-frame - (gdb-get-create-instance-buffer instance - 'gdb-command-buffer))) - - - -(defun gdb-call-showing-gud (instance command) - (gud-display-gud-buffer instance) - (comint-input-sender (gdb-instance-process instance) command)) - -(defvar gud-target-history ()) - -(defun gud-temp-buffer-show (buf) - (let ((ow (selected-window))) - (unwind-protect - (progn - (pop-to-buffer buf) - - ;; This insertion works around a bug in emacs. - ;; The bug is that all the empty space after a - ;; highlighted word that terminates a buffer - ;; gets highlighted. That's really ugly, so - ;; make sure a highlighted word can't ever - ;; terminate the buffer. - (goto-char (point-max)) - (insert "\n") - (goto-char (point-min)) - - (if (< (window-height) 10) - (enlarge-window (- 10 (window-height))))) - (select-window ow)))) - -(defun gud-target (instance command) - (interactive - (let* ((instance (gdb-needed-default-instance)) - (temp-buffer-show-function (function gud-temp-buffer-show)) - (target-name (completing-read (format "Target type: ") - '(("remote") - ("core") - ("child") - ("exec")) - nil - t - nil - 'gud-target-history))) - (list instance - (cond - ((equal target-name "child") "run") - - ((equal target-name "core") - (concat "target core " - (read-file-name "core file: " - nil - "core" - t))) - - ((equal target-name "exec") - (concat "target exec " - (read-file-name "exec file: " - nil - "a.out" - t))) - - ((equal target-name "remote") - (concat "target remote " - (read-file-name "serial line for remote: " - "/dev/" - "ttya" - t))) - - (t "echo No such target command!"))))) - - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - -(defun gud-backtrace () - (interactive) - (let ((instance (gdb-needed-default-instance))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) - "backtrace")))) - -(defun gud-frame () - (interactive) - (let ((instance (gdb-needed-default-instance))) - (apply comint-input-sender - (list (gdb-instance-process instance) - "frame")))) - -(defun gud-return (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "return " (read-string "Expression to return: "))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - - -(defun gud-file (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "file " (read-file-name "Executable to debug: " - nil - "a.out" - t))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - -(defun gud-core-file (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "core " (read-file-name "Core file to debug: " - nil - "core-file" - t))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - -(defun gud-cd (dir) - (interactive "FChange GDB's default directory: ") - (let ((instance (gdb-needed-default-instance))) - (save-excursion - (set-buffer (gdb-get-instance-buffer instance 'gud)) - (cd dir)) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) - (concat "cd " dir))))) - - -(defun gud-exec-file (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "exec-file " (read-file-name "Init memory from executable: " - nil - "a.out" - t))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - -(defun gud-load (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "load " (read-file-name "Dynamicly load from file: " - nil - "a.out" - t))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - -(defun gud-symbol-file (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "symbol-file " (read-file-name "Read symbol table from file: " - nil - "a.out" - t))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - - -(defun gud-add-symbol-file (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "add-symbol-file " - (read-file-name "Add symbols from file: " - nil - "a.out" - t))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - - -(defun gud-sharedlibrary (instance command) - (interactive - (let ((temp-buffer-show-function (function gud-temp-buffer-show))) - (list (gdb-needed-default-instance) - (concat "sharedlibrary " - (read-string "Load symbols for files matching regexp: "))))) - (gud-display-gud-buffer instance) - (apply comint-input-sender - (list (gdb-instance-process instance) command))) - - -;;;; Help - - - -;;;; Window management - - -;;; FIXME: This should only return true for buffers in the current instance -(defun gud-protected-buffer-p (buffer) - "Is BUFFER a buffer which we want to leave displayed?" - (save-excursion - (set-buffer buffer) - (or gdb-buffer-type - overlay-arrow-position))) - -;;; The way we abuse the dedicated-p flag is pretty gross, but seems -;;; to do the right thing. Seeing as there is no way for Lisp code to -;;; get at the use_time field of a window, I'm not sure there exists a -;;; more elegant solution without writing C code. - -(defun gud-display-buffer (buf &optional size) - (let ((must-split nil) - (answer nil)) - (save-excursion - (unwind-protect - (progn - (walk-windows - '(lambda (win) - (if (gud-protected-buffer-p (window-buffer win)) - (set-window-buffer-dedicated win (window-buffer win))))) - (setq answer (get-buffer-window buf)) - (if (not answer) - (let ((window (get-lru-window))) - (if (not (window-dedicated-p window)) - (progn - (set-window-buffer window buf) - (setq answer window)) - (setq must-split t))))) - (walk-windows - '(lambda (win) - (if (gud-protected-buffer-p (window-buffer win)) - (set-window-buffer-dedicated win nil))))) - (if must-split - (let* ((largest (get-largest-window)) - (cur-size (window-height largest)) - (new-size (and size (< size cur-size) (- cur-size size)))) - (setq answer (split-window largest new-size)) - (set-window-buffer answer buf))) - answer))) - -(defun existing-source-window (buffer) - (catch 'found - (save-excursion - (walk-windows - (function - (lambda (win) - (if (and overlay-arrow-position - (eq (window-buffer win) - (marker-buffer overlay-arrow-position))) - (progn - (set-window-buffer win buffer) - (throw 'found win)))))) - nil))) - -(defun gud-display-source-buffer (buffer) - (or (existing-source-window buffer) - (gud-display-buffer buffer))) - -(defun gud-display-buffer-new-frame (buf) - (save-excursion - (set-buffer buf) - (let* ((buf-height (+ 4 (count-lines (point-min) (point-max)))) - (frame-params (list (cons 'height buf-height))) - ) - ;; This is a hack so that we can re-size this window to occupy just as - ;; much space is needed. - (setq truncate-lines t) - (set-buffer-dedicated-frame buf (make-frame frame-params))))) - - - -;;; Shared keymap initialization: - -(defun gud-display-gud-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer - (gdb-get-create-instance-buffer instance 'gud))) - -(defun gud-frame-gud-buffer (instance) - (interactive (list (gdb-needed-default-instance))) - (gud-display-buffer-new-frame - (gdb-get-create-instance-buffer instance 'gud))) - - -(defun gud-gdb-find-file (f) - (find-file-noselect f)) - -;;; XEmacs: don't autoload this yet since it's still buggy - use the -;;; one in gdb.el instead -(defun gdb (command-line) - "Run gdb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-shell-command "Run gdb (like this): " - (if (consp gud-gdb-history) - (car gud-gdb-history) - "gdb ") - '(gud-gdb-history . 1)))) - (gud-overload-functions - '((gud-massage-args . gud-gdb-massage-args) - (gud-marker-filter . gud-gdb-marker-filter) - (gud-find-file . gud-gdb-find-file) - )) - - (let* ((words (gud-chop-words command-line)) - (program (car words)) - (file-word (let ((w (cdr words))) - (while (and w (= ?- (aref (car w) 0))) - (setq w (cdr w))) - (car w))) - (args (delq file-word (cdr words))) - (file (and file-word (expand-file-name file-word))) - (filepart (if file (file-name-nondirectory file) "")) - (buffer-name (concat "*" "gdb" - (and (string< "" filepart) - (concat "-" filepart)) "*"))) - (setq gdb-first-time (not (get-buffer-process buffer-name)))) - - (gud-common-init command-line "gdb") - - (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.") - (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set breakpoint at current line.") - (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") - (gud-def gud-kill "kill" nil "Kill the program.") - (gud-def gud-run "run" nil "Run the program.") - (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.") - (gud-def gud-step "step %p" "\C-s" "Step one source line with display.") - (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).") - (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") - (gud-def gud-cont "cont" "\C-r" "Continue with display.") - (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") - (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") - (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.") - - (setq comint-prompt-regexp "^(.*gdb[+]?) *") - (setq comint-input-sender 'gdb-send) - (run-hooks 'gdb-mode-hook) - (let ((instance - (make-gdb-instance (get-buffer-process (current-buffer))) - )) - (if gdb-first-time (gdb-clear-inferior-io instance))) - ) - - -;; ====================================================================== -;; sdb functions - -;;; History of argument lists passed to sdb. -(defvar gud-sdb-history nil) - -(defvar gud-sdb-needs-tags (not (file-exists-p "/var")) - "If nil, we're on a System V Release 4 and don't need the tags hack.") - -(defvar gud-sdb-lastfile nil) - -(defun gud-sdb-massage-args (file args) - (cons file args)) - -(defun gud-sdb-marker-filter (string) - (cond - ;; System V Release 3.2 uses this format - ((string-match "\\(^0x\\w* in \\|^\\|\n\\)\\([^:\n]*\\):\\([0-9]*\\):.*\n" - string) - (setq gud-last-frame - (cons - (substring string (match-beginning 2) (match-end 2)) - (string-to-int - (substring string (match-beginning 3) (match-end 3)))))) - ;; System V Release 4.0 - ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n" - string) - (setq gud-sdb-lastfile - (substring string (match-beginning 2) (match-end 2)))) - ((and gud-sdb-lastfile (string-match "^\\([0-9]+\\):" string)) - (setq gud-last-frame - (cons - gud-sdb-lastfile - (string-to-int - (substring string (match-beginning 1) (match-end 1)))))) - (t - (setq gud-sdb-lastfile nil))) - string) - -(defun gud-sdb-find-file (f) - (if gud-sdb-needs-tags - (find-tag-noselect f) - (find-file-noselect f))) - -;;;###autoload -(defun sdb (command-line) - "Run sdb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run sdb (like this): " - (if (consp gud-sdb-history) - (car gud-sdb-history) - "sdb ") - nil nil - '(gud-sdb-history . 1)))) - (if (and gud-sdb-needs-tags - (not (and (boundp 'tags-file-name) (file-exists-p tags-file-name)))) - (error "The sdb support requires a valid tags table to work.")) - (gud-overload-functions '((gud-massage-args . gud-sdb-massage-args) - (gud-marker-filter . gud-sdb-marker-filter) - (gud-find-file . gud-sdb-find-file) - )) - - (gud-common-init command-line "sdb") - - (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.") - (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.") - (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line") - (gud-def gud-step "s %p" "\C-s" "Step one source line with display.") - (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.") - (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).") - (gud-def gud-cont "c" "\C-r" "Continue with display.") - (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.") - - (setq comint-prompt-regexp "\\(^\\|\n\\)\\*") - (run-hooks 'sdb-mode-hook) - ) - -;; ====================================================================== -;; dbx functions - -;;; History of argument lists passed to dbx. -(defvar gud-dbx-history nil) - -(defun gud-dbx-massage-args (file args) - (cons file args)) - -(defun gud-dbx-marker-filter (string) - (if (or (string-match - "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\"" - string) - (string-match - "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\"" - string)) - (setq gud-last-frame - (cons - (substring string (match-beginning 2) (match-end 2)) - (string-to-int - (substring string (match-beginning 1) (match-end 1)))))) - string) - -(defun gud-dbx-find-file (f) - (find-file-noselect f)) - -;;;###autoload -(defun dbx (command-line) - "Run dbx on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run dbx (like this): " - (if (consp gud-dbx-history) - (car gud-dbx-history) - "dbx ") - nil nil - '(gud-dbx-history . 1)))) - (gud-overload-functions '((gud-massage-args . gud-dbx-massage-args) - (gud-marker-filter . gud-dbx-marker-filter) - (gud-find-file . gud-dbx-find-file) - )) - - (gud-common-init command-line "dbx") - - (gud-def gud-break "file \"%d%f\"\nstop at %l" - "\C-b" "Set breakpoint at current line.") -;; (gud-def gud-break "stop at \"%f\":%l" -;; "\C-b" "Set breakpoint at current line.") - (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") - (gud-def gud-step "step %p" "\C-s" "Step one line with display.") - (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.") - (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).") - (gud-def gud-cont "cont" "\C-r" "Continue with display.") - (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.") - (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.") - (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.") - - (setq comint-prompt-regexp "^[^)]*dbx) *") - (run-hooks 'dbx-mode-hook) - ) - -;; ====================================================================== -;; xdb (HP PARISC debugger) functions - -;;; History of argument lists passed to xdb. -(defvar gud-xdb-history nil) - -(defvar gud-xdb-directories nil - "*A list of directories that xdb should search for source code. -If nil, only source files in the program directory -will be known to xdb. - -The file names should be absolute, or relative to the directory -containing the executable being debugged.") - -(defun gud-xdb-massage-args (file args) - (nconc (let ((directories gud-xdb-directories) - (result nil)) - (while directories - (setq result (cons (car directories) (cons "-d" result))) - (setq directories (cdr directories))) - (nreverse (cons file result))) - args)) - -(defun gud-xdb-file-name (f) - "Transform a relative pathname to a full pathname in xdb mode" - (let ((result nil)) - (if (file-exists-p f) - (setq result (expand-file-name f)) - (let ((directories gud-xdb-directories)) - (while directories - (let ((path (concat (car directories) "/" f))) - (if (file-exists-p path) - (setq result (expand-file-name path) - directories nil))) - (setq directories (cdr directories))))) - result)) - -;; xdb does not print the lines all at once, so we have to accumulate them -(defvar gud-xdb-accumulation "") - -(defun gud-xdb-marker-filter (string) - (let (result) - (if (or (string-match comint-prompt-regexp string) - (string-match ".*\012" string)) - (setq result (concat gud-xdb-accumulation string) - gud-xdb-accumulation "") - (setq gud-xdb-accumulation (concat gud-xdb-accumulation string))) - (if result - (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\):" result) - (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):" - result)) - (let ((line (string-to-int - (substring result (match-beginning 2) (match-end 2)))) - (file (gud-xdb-file-name - (substring result (match-beginning 1) (match-end 1))))) - (if file - (setq gud-last-frame (cons file line)))))) - (or result ""))) - -(defun gud-xdb-find-file (f) - (let ((realf (gud-xdb-file-name f))) - (if realf (find-file-noselect realf)))) - -;;;###autoload -(defun xdb (command-line) - "Run xdb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger. - -You can set the variable 'gud-xdb-directories' to a list of program source -directories if your program contains sources from more than one directory." - (interactive - (list (read-from-minibuffer "Run xdb (like this): " - (if (consp gud-xdb-history) - (car gud-xdb-history) - "xdb ") - nil nil - '(gud-xdb-history . 1)))) - (gud-overload-functions '((gud-massage-args . gud-xdb-massage-args) - (gud-marker-filter . gud-xdb-marker-filter) - (gud-find-file . gud-xdb-find-file))) - - (gud-common-init command-line "xdb") - - (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.") - (gud-def gud-tbreak "b %f:%l\\t" "\C-t" - "Set temporary breakpoint at current line.") - (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line") - (gud-def gud-step "s %p" "\C-s" "Step one line with display.") - (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).") - (gud-def gud-cont "c" "\C-r" "Continue with display.") - (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.") - (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.") - (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.") - (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.") - - (setq comint-prompt-regexp "^>") - (make-local-variable 'gud-xdb-accumulation) - (setq gud-xdb-accumulation "") - (run-hooks 'xdb-mode-hook)) - -;; ====================================================================== -;; perldb functions - -;;; History of argument lists passed to perldb. -(defvar gud-perldb-history nil) - -(defun gud-perldb-massage-args (file args) - (cons "-d" (cons file (cons "-emacs" args)))) - -;; There's no guarantee that Emacs will hand the filter the entire -;; marker at once; it could be broken up across several strings. We -;; might even receive a big chunk with several markers in it. If we -;; receive a chunk of text which looks like it might contain the -;; beginning of a marker, we save it here between calls to the -;; filter. -(defvar gud-perldb-marker-acc "") - -(defun gud-perldb-marker-filter (string) - (save-match-data - (setq gud-perldb-marker-acc (concat gud-perldb-marker-acc string)) - (let ((output "")) - - ;; Process all the complete markers in this chunk. - (while (string-match "^\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" - gud-perldb-marker-acc) - (setq - - ;; Extract the frame position from the marker. - gud-last-frame - (cons (substring gud-perldb-marker-acc (match-beginning 1) (match-end 1)) - (string-to-int (substring gud-perldb-marker-acc - (match-beginning 2) - (match-end 2)))) - - ;; Append any text before the marker to the output we're going - ;; to return - we don't include the marker in this text. - output (concat output - (substring gud-perldb-marker-acc 0 (match-beginning 0))) - - ;; Set the accumulator to the remaining text. - gud-perldb-marker-acc (substring gud-perldb-marker-acc (match-end 0)))) - - ;; Does the remaining text look like it might end with the - ;; beginning of another marker? If it does, then keep it in - ;; gud-perldb-marker-acc until we receive the rest of it. Since we - ;; know the full marker regexp above failed, it's pretty simple to - ;; test for marker starts. - (if (string-match "^\032.*\\'" gud-perldb-marker-acc) - (progn - ;; Everything before the potential marker start can be output. - (setq output (concat output (substring gud-perldb-marker-acc - 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq gud-perldb-marker-acc - (substring gud-perldb-marker-acc (match-beginning 0)))) - - (setq output (concat output gud-perldb-marker-acc) - gud-perldb-marker-acc "")) - - output))) - -(defun gud-perldb-find-file (f) - (find-file-noselect f)) - -;;;###autoload -(defun perldb (command-line) - "Run perldb on program FILE in buffer *gud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run perldb (like this): " - (if (consp gud-perldb-history) - (car gud-perldb-history) - "perl ") - nil nil - '(gud-perldb-history . 1)))) - (gud-overload-functions '((gud-massage-args . gud-perldb-massage-args) - (gud-marker-filter . gud-perldb-marker-filter) - (gud-find-file . gud-perldb-find-file) - )) - - (gud-common-init command-line "perldb") - - (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.") - (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line") - (gud-def gud-step "s" "\C-s" "Step one source line with display.") - (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") - (gud-def gud-cont "c" "\C-r" "Continue with display.") -; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.") -; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") -; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") - (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.") - - (setq comint-prompt-regexp "^ DB<[0-9]+> ") - (run-hooks 'perldb-mode-hook) - ) - -;; -;; End of debugger-specific information -;; - - -;;; When we send a command to the debugger via gud-call, it's annoying -;;; to see the command and the new prompt inserted into the debugger's -;;; buffer; we have other ways of knowing the command has completed. -;;; -;;; If the buffer looks like this: -;;; -------------------- -;;; (gdb) set args foo bar -;;; (gdb) -!- -;;; -------------------- -;;; (the -!- marks the location of point), and we type `C-x SPC' in a -;;; source file to set a breakpoint, we want the buffer to end up like -;;; this: -;;; -------------------- -;;; (gdb) set args foo bar -;;; Breakpoint 1 at 0x92: file make-docfile.c, line 49. -;;; (gdb) -!- -;;; -------------------- -;;; Essentially, the old prompt is deleted, and the command's output -;;; and the new prompt take its place. -;;; -;;; Not echoing the command is easy enough; you send it directly using -;;; comint-input-sender, and it never enters the buffer. However, -;;; getting rid of the old prompt is trickier; you don't want to do it -;;; when you send the command, since that will result in an annoying -;;; flicker as the prompt is deleted, redisplay occurs while Emacs -;;; waits for a response from the debugger, and the new prompt is -;;; inserted. Instead, we'll wait until we actually get some output -;;; from the subprocess before we delete the prompt. If the command -;;; produced no output other than a new prompt, that prompt will most -;;; likely be in the first chunk of output received, so we will delete -;;; the prompt and then replace it with an identical one. If the -;;; command produces output, the prompt is moving anyway, so the -;;; flicker won't be annoying. -;;; -;;; So - when we want to delete the prompt upon receipt of the next -;;; chunk of debugger output, we position gud-delete-prompt-marker at -;;; the start of the prompt; the process filter will notice this, and -;;; delete all text between it and the process output marker. If -;;; gud-delete-prompt-marker points nowhere, we leave the current -;;; prompt alone. -(defvar gud-delete-prompt-marker nil) - - -(defvar gdbish-comint-mode-map (copy-keymap comint-mode-map)) -(define-key gdbish-comint-mode-map "\C-c\M-\C-r" 'gud-display-registers-buffer) -(define-key gdbish-comint-mode-map "\C-c\M-\C-f" 'gud-display-stack-buffer) -(define-key gdbish-comint-mode-map "\C-c\M-\C-b" 'gud-display-breakpoints-buffer) - -(defun gud-mode () - "Major mode for interacting with an inferior debugger process. - - You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx, -or M-x xdb. Each entry point finishes by executing a hook; `gdb-mode-hook', -`sdb-mode-hook', `dbx-mode-hook' or `xdb-mode-hook' respectively. - -After startup, the following commands are available in both the GUD -interaction buffer and any source buffer GUD visits due to a breakpoint stop -or step operation: - -\\[gud-break] sets a breakpoint at the current file and line. In the -GUD buffer, the current file and line are those of the last breakpoint or -step. In a source buffer, they are the buffer's file and current line. - -\\[gud-remove] removes breakpoints on the current file and line. - -\\[gud-refresh] displays in the source window the last line referred to -in the gud buffer. - -\\[gud-step], \\[gud-next], and \\[gud-stepi] do a step-one-line, -step-one-line (not entering function calls), and step-one-instruction -and then update the source window with the current file and position. -\\[gud-cont] continues execution. - -\\[gud-print] tries to find the largest C lvalue or function-call expression -around point, and sends it to the debugger for value display. - -The above commands are common to all supported debuggers except xdb which -does not support stepping instructions. - -Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break], -except that the breakpoint is temporary; that is, it is removed when -execution stops on it. - -Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack -frame. \\[gud-down] drops back down through one. - -If you are using gdb or xdb, \\[gud-finish] runs execution to the return from -the current function and stops. - -All the keystrokes above are accessible in the GUD buffer -with the prefix C-c, and in all buffers through the prefix C-x C-a. - -All pre-defined functions for which the concept make sense repeat -themselves the appropriate number of times if you give a prefix -argument. - -You may use the `gud-def' macro in the initialization hook to define other -commands. - -Other commands for interacting with the debugger process are inherited from -comint mode, which see." - (interactive) - (comint-mode) - (setq major-mode 'gud-mode) - (setq mode-name "Debugger") - (setq mode-line-process '(": %s")) - (use-local-map (copy-keymap gdbish-comint-mode-map)) - (setq gud-last-frame nil) - (make-local-variable 'comint-prompt-regexp) - (make-local-variable 'gud-delete-prompt-marker) - (setq gud-delete-prompt-marker (make-marker)) - (run-hooks 'gud-mode-hook) -) - -(defvar gud-comint-buffer nil) - -;; Chop STRING into words separated by SPC or TAB and return a list of them. -(defun gud-chop-words (string) - (let ((i 0) (beg 0) - (len (length string)) - (words nil)) - (while (< i len) - (if (memq (aref string i) '(?\t ? )) - (progn - (setq words (cons (substring string beg i) words) - beg (1+ i)) - (while (and (< beg len) (memq (aref string beg) '(?\t ? ))) - (setq beg (1+ beg))) - (setq i (1+ beg))) - (setq i (1+ i)))) - (if (< beg len) - (setq words (cons (substring string beg) words))) - (nreverse words))) - -(defvar gud-target-name "--unknown--" - "The apparent name of the program being debugged in a gud buffer. -For sure this the root string used in smashing together the gud -buffer's name, even if that doesn't happen to be the name of a -program.") - -;; Perform initializations common to all debuggers. -(defun gud-common-init (command-line debugger-name) - (let* ((words (gud-chop-words command-line)) - (program (car words)) - (file-word (let ((w (cdr words))) - (while (and w (= ?- (aref (car w) 0))) - (setq w (cdr w))) - (car w))) - (args (delq file-word (cdr words))) - (file (and file-word (expand-file-name file-word))) - (filepart (if file (file-name-nondirectory file) "")) - (buffer-name (concat "*" debugger-name - (and (string< "" filepart) - (concat "-" filepart)) "*"))) - (switch-to-buffer buffer-name) - (if file - (setq default-directory (file-name-directory file))) - (or (bolp) (newline)) - (insert "Current directory is " default-directory "\n") - (let ((old-instance gdb-buffer-instance)) - (apply 'make-comint (concat debugger-name - (and (string< "" filepart) - (concat "-" filepart))) - program nil - ;; There *has* to be an easier way to strip "nil"s from the output - ;; of gud-massage-args - (apply 'append (mapcar '(lambda (arg) (if (stringp arg) (list arg) arg)) - (gud-massage-args file args)))) - (gud-mode) - (make-variable-buffer-local 'old-gdb-buffer-instance) - (setq old-gdb-buffer-instance old-instance)) - (make-variable-buffer-local 'gud-target-name) - (setq gud-target-name filepart)) - (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter) - (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel) - (gud-set-buffer) - ) - -(defun gud-set-buffer () - (cond ((eq major-mode 'gud-mode) - (setq gud-comint-buffer (current-buffer))))) - -;; These functions are responsible for inserting output from your debugger -;; into the buffer. The hard work is done by the method that is -;; the value of gud-marker-filter. - -(defun gud-filter (proc string) - ;; Here's where the actual buffer insertion is done - (let ((inhibit-quit t)) - (save-excursion - (set-buffer (process-buffer proc)) - (let (moving output-after-point) - (save-excursion - (goto-char (process-mark proc)) - ;; If we have been so requested, delete the debugger prompt. - (if (marker-buffer gud-delete-prompt-marker) - (progn - (delete-region (point) gud-delete-prompt-marker) - (set-marker gud-delete-prompt-marker nil))) - (insert-before-markers (gud-marker-filter string)) - (setq moving (= (point) (process-mark proc))) - (setq output-after-point (< (point) (process-mark proc))) - ;; Check for a filename-and-line number. - ;; Don't display the specified file - ;; unless (1) point is at or after the position where output appears - ;; and (2) this buffer is on the screen. - (if (and gud-last-frame - (not output-after-point) - (get-buffer-window (current-buffer))) - (gud-display-frame))) - (if moving (goto-char (process-mark proc))))))) - -(defun gud-proc-died (proc) - ;; Stop displaying an arrow in a source file. - (setq overlay-arrow-position nil) - - ;; Kill the dummy process, so that C-x C-c won't worry about it. - (save-excursion - (set-buffer (process-buffer proc)) - (let ((buf (gdb-get-instance-buffer gdb-buffer-instance - 'gdb-inferior-io))) - (if buf - (kill-process (get-buffer-process buf))) - ))) - -(defun gud-sentinel (proc msg) - (cond ((null (buffer-name (process-buffer proc))) - ;; buffer killed - (gud-proc-died proc) - (set-process-buffer proc nil)) - ((memq (process-status proc) '(signal exit)) - (gud-proc-died proc) - - ;; Fix the mode line. - (setq mode-line-process - (concat ": " - (symbol-name (process-status proc)))) - (let* ((obuf (current-buffer))) - ;; save-excursion isn't the right thing if - ;; process-buffer is current-buffer - (unwind-protect - (progn - ;; Write something in *compilation* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) - (if (eobp) - (insert ?\n mode-name " " msg) - (save-excursion - (goto-char (point-max)) - (insert ?\n mode-name " " msg))) - ;; If buffer and mode line will show that the process - ;; is dead, we can delete it now. Otherwise it - ;; will stay around until M-x list-processes. - (delete-process proc)) - ;; Restore old buffer, but don't restore old point - ;; if obuf is the gud buffer. - (set-buffer obuf)))))) - -(defun gud-display-frame () - "Find and obey the last filename-and-line marker from the debugger. -Obeying it means displaying in another window the specified file and line." - (interactive) - (if gud-last-frame - (progn -; (gud-set-buffer) - (gud-display-line (car gud-last-frame) (cdr gud-last-frame)) - (setq gud-last-last-frame gud-last-frame - gud-last-frame nil)))) - -;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen -;; and that its line LINE is visible. -;; Put the overlay-arrow on the line LINE in that buffer. -;; Most of the trickiness in here comes from wanting to preserve the current -;; region-restriction if that's possible. We use an explicit display-buffer -;; to get around the fact that this is called inside a save-excursion. - -(defun gud-display-line (true-file line) - (let* ((buffer (gud-find-file true-file)) - (window (gud-display-source-buffer buffer)) - (pos)) - (if (not window) - (error "foo bar baz")) -;;; (if (equal buffer (current-buffer)) -;;; nil -;;; (setq buffer-read-only nil)) - (save-excursion -;;; (setq buffer-read-only t) - (set-buffer buffer) - (save-restriction - (widen) - (goto-line line) - (setq pos (point)) - (setq overlay-arrow-string "=>") - (or overlay-arrow-position - (setq overlay-arrow-position (make-marker))) - (set-marker overlay-arrow-position (point) (current-buffer))) - (cond ((or (< pos (point-min)) (> pos (point-max))) - (widen) - (goto-char pos)))) - (set-window-point window overlay-arrow-position))) - -;;; The gud-call function must do the right thing whether its invoking -;;; keystroke is from the GUD buffer itself (via major-mode binding) -;;; or a C buffer. In the former case, we want to supply data from -;;; gud-last-frame. Here's how we do it: - -(defun gud-format-command (str arg) - (let ((insource (not (eq (current-buffer) gud-comint-buffer)))) - (if (string-match "\\(.*\\)%f\\(.*\\)" str) - (setq str (concat - (substring str (match-beginning 1) (match-end 1)) - (file-name-nondirectory (if insource - (buffer-file-name) - (car gud-last-frame))) - (substring str (match-beginning 2) (match-end 2))))) - (if (string-match "\\(.*\\)%d\\(.*\\)" str) - (setq str (concat - (substring str (match-beginning 1) (match-end 1)) - (file-name-directory (if insource - (buffer-file-name) - (car gud-last-frame))) - (substring str (match-beginning 2) (match-end 2))))) - (if (string-match "\\(.*\\)%l\\(.*\\)" str) - (setq str (concat - (substring str (match-beginning 1) (match-end 1)) - (if insource - (save-excursion - (beginning-of-line) - (save-restriction (widen) - (1+ (count-lines 1 (point))))) - (cdr gud-last-frame)) - (substring str (match-beginning 2) (match-end 2))))) - (if (string-match "\\(.*\\)%e\\(.*\\)" str) - (setq str (concat - (substring str (match-beginning 1) (match-end 1)) - (find-c-expr) - (substring str (match-beginning 2) (match-end 2))))) - (if (string-match "\\(.*\\)%a\\(.*\\)" str) - (setq str (concat - (substring str (match-beginning 1) (match-end 1)) - (gud-read-address) - (substring str (match-beginning 2) (match-end 2))))) - (if (string-match "\\(.*\\)%p\\(.*\\)" str) - (setq str (concat - (substring str (match-beginning 1) (match-end 1)) - (if arg (int-to-string arg) "") - (substring str (match-beginning 2) (match-end 2))))) - ) - str - ) - -(defun gud-read-address () - "Return a string containing the core-address found in the buffer at point." - (save-excursion - (let ((pt (point)) found begin) - (setq found (if (search-backward "0x" (- pt 7) t) (point))) - (cond - (found (forward-char 2) - (buffer-substring found - (progn (re-search-forward "[^0-9a-f]") - (forward-char -1) - (point)))) - (t (setq begin (progn (re-search-backward "[^0-9]") - (forward-char 1) - (point))) - (forward-char 1) - (re-search-forward "[^0-9]") - (forward-char -1) - (buffer-substring begin (point))))))) - -(defun gud-call (fmt &optional arg) - (let ((msg (gud-format-command fmt arg))) - (message "Command: %s" msg) - (sit-for 0) - (gud-basic-call msg))) - -(defun gud-basic-call (command) - "Invoke the debugger COMMAND displaying source in other window." - (interactive) - (gud-set-buffer) - (let ((proc (get-buffer-process gud-comint-buffer))) - - ;; Arrange for the current prompt to get deleted. - (save-excursion - (set-buffer gud-comint-buffer) - (goto-char (process-mark proc)) - (beginning-of-line) - (if (looking-at comint-prompt-regexp) - (set-marker gud-delete-prompt-marker (point))) - (apply comint-input-sender (list proc command))))) - -(defun gud-refresh (&optional arg) - "Fix up a possibly garbled display, and redraw the arrow." - (interactive "P") - (recenter arg) - (or gud-last-frame (setq gud-last-frame gud-last-last-frame)) - (gud-display-frame)) - -;;; Count windows on a given frame -;; -(defun count-frame-windows (frame &optional minibuf) - "Returns the number of visible windows on FRAME. -Optional arg NO-MINI non-nil means don't count the minibuffer -even if it is active." - (let ((count 0)) - (walk-windows (function (lambda (w) - (if (eq (window-frame w) frame) - (setq count (+ count 1))))) - minibuf t) - count)) - - -;; Attempt to fit a frame so that it is just large enough to display buf -;; Only changes the frame size if it has just one window and we can only -;; make the attempt if the buffer has truncate-lines set (otherwise it's -;; too painful to work out how many lines we need. -;; Doesn't even *attempt* to cope with fontified buffers. - -(defun fit-frame-to-buffer (frame buf) - (let (height-needed) - (if (and frame - truncate-lines - (<= (count-frame-windows frame) 1)) - (progn - (setq height-needed - (+ (count-lines (point-min) (point-max)) 2)) - (cond - ((> (frame-height frame) height-needed) - (set-frame-height frame height-needed)) - ((< height-needed 24) - (set-frame-height frame height-needed)) - (t - (set-frame-height frame 24))))))) - -;;; Code for parsing expressions out of C code. The single entry point is -;;; find-c-expr, which tries to return an lvalue expression from around point. -;;; -;;; The rest of this file is a hacked version of gdbsrc.el by -;;; Debby Ayers , -;;; Rich Schaefer Schlumberger, Austin, Tx. - -(defun find-c-expr () - "Returns the C expr that surrounds point." - (interactive) - (save-excursion - (let ((p) (expr) (test-expr)) - (setq p (point)) - (setq expr (expr-cur)) - (setq test-expr (expr-prev)) - (while (expr-compound test-expr expr) - (setq expr (cons (car test-expr) (cdr expr))) - (goto-char (car expr)) - (setq test-expr (expr-prev))) - (goto-char p) - (setq test-expr (expr-next)) - (while (expr-compound expr test-expr) - (setq expr (cons (car expr) (cdr test-expr))) - (setq test-expr (expr-next)) - ) - (buffer-substring (car expr) (cdr expr))))) - -(defun expr-cur () - "Returns the expr that point is in; point is set to beginning of expr. -The expr is represented as a cons cell, where the car specifies the point in -the current buffer that marks the beginning of the expr and the cdr specifies -the character after the end of the expr." - (let ((p (point)) (begin) (end)) - (expr-backward-sexp) - (setq begin (point)) - (expr-forward-sexp) - (setq end (point)) - (if (>= p end) - (progn - (setq begin p) - (goto-char p) - (expr-forward-sexp) - (setq end (point)) - ) - ) - (goto-char begin) - (cons begin end))) - -(defun expr-backward-sexp () - "Version of `backward-sexp' that catches errors." - (condition-case nil - (backward-sexp) - (error t))) - -(defun expr-forward-sexp () - "Version of `forward-sexp' that catches errors." - (condition-case nil - (forward-sexp) - (error t))) - -(defun expr-prev () - "Returns the previous expr, point is set to beginning of that expr. -The expr is represented as a cons cell, where the car specifies the point in -the current buffer that marks the beginning of the expr and the cdr specifies -the character after the end of the expr" - (let ((begin) (end)) - (expr-backward-sexp) - (setq begin (point)) - (expr-forward-sexp) - (setq end (point)) - (goto-char begin) - (cons begin end))) - -(defun expr-next () - "Returns the following expr, point is set to beginning of that expr. -The expr is represented as a cons cell, where the car specifies the point in -the current buffer that marks the beginning of the expr and the cdr specifies -the character after the end of the expr." - (let ((begin) (end)) - (expr-forward-sexp) - (expr-forward-sexp) - (setq end (point)) - (expr-backward-sexp) - (setq begin (point)) - (cons begin end))) - -(defun expr-compound-sep (span-start span-end) - "Returns '.' for '->' & '.', returns ' ' for white space, -returns '?' for other punctuation." - (let ((result ? ) - (syntax)) - (while (< span-start span-end) - (setq syntax (char-syntax (char-after span-start))) - (cond - ((= syntax ? ) t) - ((= syntax ?.) (setq syntax (char-after span-start)) - (cond - ((= syntax ?.) (setq result ?.)) - ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>)) - (setq result ?.) - (setq span-start (+ span-start 1))) - (t (setq span-start span-end) - (setq result ??))))) - (setq span-start (+ span-start 1))) - result)) - -(defun expr-compound (first second) - "Non-nil if concatenating FIRST and SECOND makes a single C token. -The two exprs are represented as a cons cells, where the car -specifies the point in the current buffer that marks the beginning of the -expr and the cdr specifies the character after the end of the expr. -Link exprs of the form: - Expr -> Expr - Expr . Expr - Expr (Expr) - Expr [Expr] - (Expr) Expr - [Expr] Expr" - (let ((span-start (cdr first)) - (span-end (car second)) - (syntax)) - (setq syntax (expr-compound-sep span-start span-end)) - (cond - ((= (car first) (car second)) nil) - ((= (cdr first) (cdr second)) nil) - ((= syntax ?.) t) - ((= syntax ? ) - (setq span-start (char-after (- span-start 1))) - (setq span-end (char-after span-end)) - (cond - ((= span-start ?) ) t ) - ((= span-start ?] ) t ) - ((= span-end ?( ) t ) - ((= span-end ?[ ) t ) - (t nil)) - ) - (t nil)))) - - -;;; Compare two buffers. We assume that they're not narrowed. -(defun gud-buffers-differ (buffer1 buffer2) - (save-excursion - (let ((size1 (progn (set-buffer buffer1) (buffer-size))) - (size2 (progn (set-buffer buffer2) (buffer-size)))) - (cond - ((not (= size1 size2)) - t) - ((= (compare-buffer-substrings - buffer1 1 size1 - buffer2 1 size2) 0) - nil) - (t))))) - - -(provide 'gud) - -;; WTF -(defmacro gud (form) - (` (save-excursion (set-buffer "*gud-a.out*") (, form)))) - -(defun dbug (foo &optional fun) - (save-excursion - (set-buffer (get-buffer-create "*trace*")) - (goto-char (point-max)) - (insert "***" (symbol-name foo) "\n") - (if fun - (funcall fun)))) - - - -;;; gud.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/history.el --- a/lisp/comint/history.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -;;; history.el --- Generic history stuff - -;; Copyright (C) 1989 Free Software Foundation, Inc. - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; suggested generic history stuff -- tale - -;; This is intended to provided easy access to a list of elements -;; being kept as a history ring. - -;; To use, variables for a list and the index to it need to be kept, and -;; a limit to how large the list can grow. Short wrappers can than be provided -;; to interact with these functions. - -;; For example, a typical application of this is in interactive processes, -;; like shell or gdb. A history can be kept of commands that are sent -;; to the process so that they are easily retrieved for re-inspection or -;; re-use. Using process "foo" to illustrate: - -;; Variable foo-history will be the list. foo-history-index would be the -;; pointer to the current item within the list; it is based with 0 being -;; the most recent element added to the list. foo-history-size can be a -;; user-variable which controls how many items are allowed to exist. - -;; The following functions could interactive with the list; foo-mark -;; in these examples trackes the end of output from foo-process. - -;; (defun foo-history-previous (arg) ;; Suggested binding: C-c C-p -;; "Retrieve the previous command sent to the foo process. -;; ARG means to select that message out of the list (0 is the first)." -;; (interactive "P") -;; (history-fetch 'foo-history 'foo-history-index (or arg 'previous) -;; foo-mark (point-max))) - -;; foo-history-next would look practically the same, but substituting "next" -;; for "previous". Suggested binding: C-c C-n - -;; (defun foo-history-clear () ;; Suggested binding: C-c C-u -;; "Clear the input region for the foo-process and reset history location." -;; (interactive) -;; (delete-region foo-mark (goto-char (point-max)))) - -;; To get the history on the stack, an extremely minimal function would look -;; something like this, probably bound to RET: - -;; (defun foo-send () -;; "Send a command to foo-process." -;; (interactive) -;; (let ((str (buffer-substring foo-mark (goto-char (point-max))))) -;; (insert ?\C-j) -;; (setq foo-history-index -1) ; reset the index -;; (set-marker foo-mark (point)) -;; (send-string foo-process str) -;; (history-add 'foo-history str foo-history-size))) - -;; ToDo: history-isearch - -;;; Code: - -(provide 'history) - -(defvar history-last-search "" - "The last regexp used by history-search which resulted in a match.") - -(defun history-add (list item size) - "At the head of LIST append ITEM. Limit the length of LIST to SIZE elements. -LIST should be the name of the list." - (set list (append (list item) (eval list))) - (let ((elist (eval list))) - (if (> (length elist) size) - (setcdr (nthcdr (1- size) elist) nil)))) - -(defun history-fetch (list index dir &optional beg end) - "Retrieve an entry from LIST, working from INDEX in direction DIR. -LIST should be the name of the list, for message purposes. INDEX should be -the name of the variable used to index the list, so it can be maintained. -DIR non-nil means to use previous entry, unless it is the symbol ``next'' -to get the next entry or a number to get an absolute reference. DIR -nil is equivalent to ``next''. - -If optional numeric argument BEG is preset, it is taken as the point to insert -the entry in the current buffer, leaving point at the start of the entry. -If followed by a numeric END, the region between BEG and END will be deleted -before the entry is inserted." - (let (str (eind (eval index)) (elist (eval list))) - (cond - ((numberp dir) - (setq str (nth dir elist)) - (if str (set index dir) (message "No entry %d in %s." dir list))) - ((or (not dir) (eq dir 'next)) - (if (= eind -1) - (message "No next entry in %s." list) - (set index (1- eind)) - (setq str (if (zerop eind) "" (nth (1- eind) elist))))) - (t - (if (>= (1+ eind) (length elist)) - (message "No previous entry in %s." list) - (set index (1+ eind)) - (setq str (nth (1+ eind) elist))))) - (if (not (and (integer-or-marker-p beg) str)) () - (if (integer-or-marker-p end) (delete-region beg end)) - (insert str) - (goto-char beg)) - str)) - -(defun history-search (list index dir regexp &optional beg end) - "In history LIST, starting at INDEX and working in direction DIR, find REGEXP. -LIST and INDEX should be their respective symbol names. DIR nil or 'forward -means to search from the current index toward the most recent history entry. -DIR non-nil means to search toward the oldest entry. The current entry is -not checked in either case. - -If an entry is found and optional numeric argument BEG exists then the entry -will be inserted there and point left at BEG. If numeric END also exists -then the region will be deleted between BEG and END." - (let* ((forw (or (not dir) (eq dir 'forward))) str found - (eind (eval index)) - (elist (eval list)) - (slist (if forw - (nthcdr (- (length elist) eind) (reverse elist)) - (nthcdr (1+ eind) elist)))) - (while (and (not found) slist) - (if (string-match regexp (car slist)) - (setq found (car slist) - history-last-search regexp)) - (setq eind (+ (if forw -1 1) eind) - slist (cdr slist))) - (if (not found) - (error "\"%s\" not found %s in %s" - regexp (if forw "forward" "backward") list) - (set index eind) - (if (not (integer-or-marker-p beg)) () - (if (integer-or-marker-p end) (delete-region beg end)) - (insert found) - (goto-char beg))) - found)) - -(defun history-menu (list buffer &optional notemp) - "Show the history kept by LIST in BUFFER. -This function will use ``with-output-to-temp-buffer'' unless optional third -argument NOTEMP is non-nil." - (let ((pop-up-windows t) (line 0) - (menu - (mapconcat (function (lambda (item) - (setq line (1+ line)) - (format (format "%%%dd: %%s" - (int-to-string (length list))) - line item))) - list "\n"))) - (if notemp - (save-excursion - (insert menu) - (display-buffer buffer)) - (with-output-to-temp-buffer buffer (princ menu))))) - -;;; history.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/inf-lisp.el --- a/lisp/comint/inf-lisp.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,636 +0,0 @@ -;;; inf-lisp.el --- an inferior-lisp mode -;;; Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc. - -;; Author: Olin Shivers -;; Keywords: processes, lisp - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;;; Hacked from tea.el by Olin Shivers (shivers@cs.cmu.edu). 8/88 - -;;; This file defines a a lisp-in-a-buffer package (inferior-lisp -;;; mode) built on top of comint mode. This version is more -;;; featureful, robust, and uniform than the Emacs 18 version. The -;;; key bindings are also more compatible with the bindings of Hemlock -;;; and Zwei (the Lisp Machine emacs). - -;;; Since this mode is built on top of the general command-interpreter-in- -;;; a-buffer mode (comint mode), it shares a common base functionality, -;;; and a common set of bindings, with all modes derived from comint mode. -;;; This makes these modes easier to use. - -;;; For documentation on the functionality provided by comint mode, and -;;; the hooks available for customizing it, see the file comint.el. -;;; For further information on inferior-lisp mode, see the comments below. - -;;; Needs fixin: -;;; The load-file/compile-file default mechanism could be smarter -- it -;;; doesn't know about the relationship between filename extensions and -;;; whether the file is source or executable. If you compile foo.lisp -;;; with compile-file, then the next load-file should use foo.bin for -;;; the default, not foo.lisp. This is tricky to do right, particularly -;;; because the extension for executable files varies so much (.o, .bin, -;;; .lbin, .mo, .vo, .ao, ...). -;;; -;;; It would be nice if inferior-lisp (and inferior scheme, T, ...) modes -;;; had a verbose minor mode wherein sending or compiling defuns, etc. -;;; would be reflected in the transcript with suitable comments, e.g. -;;; ";;; redefining fact". Several ways to do this. Which is right? -;;; -;;; When sending text from a source file to a subprocess, the process-mark can -;;; move off the window, so you can lose sight of the process interactions. -;;; Maybe I should ensure the process mark is in the window when I send -;;; text to the process? Switch selectable? - -;;; Code: - -(require 'comint) -(require 'lisp-mode) - - -;;;jwz: ilisp is better, don't ###autoload -(defvar inferior-lisp-filter-regexp "\\`\\s *\\(:\\(\\w\\|\\s_\\)\\)?\\s *\\'" - "*What not to save on inferior Lisp's input history. -Input matching this regexp is not saved on the input history in Inferior Lisp -mode. Default is whitespace followed by 0 or 1 single-letter colon-keyword -\(as in :a, :c, etc.)") - -(defvar inferior-lisp-mode-map nil) -(cond ((not inferior-lisp-mode-map) - (setq inferior-lisp-mode-map (make-sparse-keymap)) - (set-keymap-name inferior-lisp-mode-map 'inferior-lisp-mode-map) - (set-keymap-parents inferior-lisp-mode-map - (list comint-mode-map shared-lisp-mode-map)) - (define-key inferior-lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) - (define-key inferior-lisp-mode-map "\C-c\C-l" 'lisp-load-file) - (define-key inferior-lisp-mode-map "\C-c\C-k" 'lisp-compile-file) - (define-key inferior-lisp-mode-map "\C-c\C-a" 'lisp-show-arglist) - (define-key inferior-lisp-mode-map "\C-c\C-d" 'lisp-describe-sym) - (define-key inferior-lisp-mode-map "\C-c\C-f" - 'lisp-show-function-documentation) - (define-key inferior-lisp-mode-map "\C-c\C-v" - 'lisp-show-variable-documentation))) - -;;; These commands augment Lisp mode, so you can process Lisp code in -;;; the source files. -(define-key lisp-mode-map "\M-\C-x" 'lisp-eval-defun) ; Gnu convention -(define-key lisp-mode-map "\C-x\C-e" 'lisp-eval-last-sexp) ; Gnu convention -(define-key lisp-mode-map "\C-c\C-e" 'lisp-eval-defun) -(define-key lisp-mode-map "\C-c\C-r" 'lisp-eval-region) -(define-key lisp-mode-map "\C-c\C-c" 'lisp-compile-defun) -(define-key lisp-mode-map "\C-c\C-z" 'switch-to-lisp) -(define-key lisp-mode-map "\C-c\C-l" 'lisp-load-file) -(define-key lisp-mode-map "\C-c\C-k" 'lisp-compile-file) ; "kompile" file -(define-key lisp-mode-map "\C-c\C-a" 'lisp-show-arglist) -(define-key lisp-mode-map "\C-c\C-d" 'lisp-describe-sym) -(define-key lisp-mode-map "\C-c\C-f" 'lisp-show-function-documentation) -(define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation) - -;;; This function exists for backwards compatibility. -;;; Previous versions of this package bound commands to C-c -;;; bindings, which is not allowed by the gnumacs standard. - -;;; "This function binds many inferior-lisp commands to C-c bindings, -;;;where they are more accessible. C-c bindings are reserved for the -;;;user, so these bindings are non-standard. If you want them, you should -;;;have this function called by the inferior-lisp-load-hook: -;;; (setq inferior-lisp-load-hook '(inferior-lisp-install-letter-bindings)) -;;;You can modify this function to install just the bindings you want." -(defun inferior-lisp-install-letter-bindings () - (define-key lisp-mode-map "\C-ce" 'lisp-eval-defun-and-go) - (define-key lisp-mode-map "\C-cr" 'lisp-eval-region-and-go) - (define-key lisp-mode-map "\C-cc" 'lisp-compile-defun-and-go) - (define-key lisp-mode-map "\C-cz" 'switch-to-lisp) - (define-key lisp-mode-map "\C-cl" 'lisp-load-file) - (define-key lisp-mode-map "\C-ck" 'lisp-compile-file) - (define-key lisp-mode-map "\C-ca" 'lisp-show-arglist) - (define-key lisp-mode-map "\C-cd" 'lisp-describe-sym) - (define-key lisp-mode-map "\C-cf" 'lisp-show-function-documentation) - (define-key lisp-mode-map "\C-cv" 'lisp-show-variable-documentation) - - (define-key inferior-lisp-mode-map "\C-cl" 'lisp-load-file) - (define-key inferior-lisp-mode-map "\C-ck" 'lisp-compile-file) - (define-key inferior-lisp-mode-map "\C-ca" 'lisp-show-arglist) - (define-key inferior-lisp-mode-map "\C-cd" 'lisp-describe-sym) - (define-key inferior-lisp-mode-map "\C-cf" 'lisp-show-function-documentation) - (define-key inferior-lisp-mode-map "\C-cv" - 'lisp-show-variable-documentation)) - - -;;;jwz: ilisp is better, don't ###autoload -(defvar inferior-lisp-program "lisp" - "*Program name for invoking an inferior Lisp with for Inferior Lisp mode.") - -;;;jwz: ilisp is better, don't ###autoload -(defvar inferior-lisp-load-command "(load \"%s\")\n" - "*Format-string for building a Lisp expression to load a file. -This format string should use `%s' to substitute a file name -and should result in a Lisp expression that will command the inferior Lisp -to load that file. The default works acceptably on most Lisps. -The string \"(progn (load \\\"%s\\\" :verbose nil :print t) (values))\\n\" -produces cosmetically superior output for this application, -but it works only in Common Lisp.") - -;;;jwz: ilisp is better, don't ###autoload -(defvar inferior-lisp-prompt "^[^> \n]*>+:? *" - "Regexp to recognise prompts in the Inferior Lisp mode. -Defaults to \"^[^> \\n]*>+:? *\", which works pretty good for Lucid, kcl, -and franz. This variable is used to initialize `comint-prompt-regexp' in the -Inferior Lisp buffer. - -More precise choices: -Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\" -franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\" -kcl: \"^>+ *\" - -This is a fine thing to set in your .emacs file.") - -(defvar inferior-lisp-buffer nil "*The current inferior-lisp process buffer. - -MULTIPLE PROCESS SUPPORT -=========================================================================== -To run multiple Lisp processes, you start the first up -with \\[inferior-lisp]. It will be in a buffer named `*inferior-lisp*'. -Rename this buffer with \\[rename-buffer]. You may now start up a new -process with another \\[inferior-lisp]. It will be in a new buffer, -named `*inferior-lisp*'. You can switch between the different process -buffers with \\[switch-to-buffer]. - -Commands that send text from source buffers to Lisp processes -- -like `lisp-eval-defun' or `lisp-show-arglist' -- have to choose a process -to send to, when you have more than one Lisp process around. This -is determined by the global variable `inferior-lisp-buffer'. Suppose you -have three inferior Lisps running: - Buffer Process - foo inferior-lisp - bar inferior-lisp<2> - *inferior-lisp* inferior-lisp<3> -If you do a \\[lisp-eval-defun] command on some Lisp source code, -what process do you send it to? - -- If you're in a process buffer (foo, bar, or *inferior-lisp*), - you send it to that process. -- If you're in some other buffer (e.g., a source file), you - send it to the process attached to buffer `inferior-lisp-buffer'. -This process selection is performed by function `inferior-lisp-proc'. - -Whenever \\[inferior-lisp] fires up a new process, it resets -`inferior-lisp-buffer' to be the new process's buffer. If you only run -one process, this does the right thing. If you run multiple -processes, you can change `inferior-lisp-buffer' to another process -buffer with \\[set-variable].") - -;;;jwz: ilisp is better, don't ###autoload -(defvar inferior-lisp-mode-hook '() - "*Hook for customizing Inferior Lisp mode.") - -(defun inferior-lisp-mode () - "Major mode for interacting with an inferior Lisp process. -Runs a Lisp interpreter as a subprocess of Emacs, with Lisp I/O through an -Emacs buffer. Variable `inferior-lisp-program' controls which Lisp interpreter -is run. Variables `inferior-lisp-prompt', `inferior-lisp-filter-regexp' and -`inferior-lisp-load-command' can customize this mode for different Lisp -interpreters. - -For information on running multiple processes in multiple buffers, see -documentation for variable `inferior-lisp-buffer'. - -\\{inferior-lisp-mode-map} - -Customization: Entry to this mode runs the hooks on `comint-mode-hook' and -`inferior-lisp-mode-hook' (in that order). - -You can send text to the inferior Lisp process from other buffers containing -Lisp source. - switch-to-lisp switches the current buffer to the Lisp process buffer. - lisp-eval-defun sends the current defun to the Lisp process. - lisp-compile-defun compiles the current defun. - lisp-eval-region sends the current region to the Lisp process. - lisp-compile-region compiles the current region. - - Prefixing the lisp-eval/compile-defun/region commands with - a \\[universal-argument] causes a switch to the Lisp process buffer after sending - the text. - -Commands: -Return after the end of the process' output sends the text from the - end of process to point. -Return before the end of the process' output copies the sexp ending at point - to the end of the process' output, and sends it. -Delete converts tabs to spaces as it moves back. -Tab indents for Lisp; with argument, shifts rest - of expression rigidly with the current line. -C-M-q does Tab on each line starting within following expression. -Paragraphs are separated only by blank lines. Semicolons start comments. -If you accidentally suspend your process, use \\[comint-continue-subjob] -to continue it." - (interactive) - (comint-mode) - (setq comint-prompt-regexp inferior-lisp-prompt) - (setq major-mode 'inferior-lisp-mode) - (setq mode-name "Inferior Lisp") - (setq mode-line-process '(":%s")) - (lisp-mode-variables t) - (use-local-map inferior-lisp-mode-map) ;c-c c-k for "kompile" file - (setq comint-get-old-input (function lisp-get-old-input)) - (setq comint-input-filter (function lisp-input-filter)) - (setq comint-input-sentinel 'ignore) - (run-hooks 'inferior-lisp-mode-hook)) - -(defun lisp-get-old-input () - "Return a string containing the sexp ending at point." - (save-excursion - (let ((end (point))) - (backward-sexp) - (buffer-substring (point) end)))) - -(defun lisp-input-filter (str) - "t if STR does not match `inferior-lisp-filter-regexp'." - (not (string-match inferior-lisp-filter-regexp str))) - -;;;jwz: ilisp is better, don't ###autoload -(defun inferior-lisp (cmd) - "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'. -If there is a process already running in `*inferior-lisp*', just switch -to that buffer. -With argument, allows you to edit the command line (default is value -of `inferior-lisp-program'). Runs the hooks from -`inferior-lisp-mode-hook' (after the `comint-mode-hook' is run). -\(Type \\[describe-mode] in the process buffer for a list of commands.)" - (interactive (list (if current-prefix-arg - (read-string "Run lisp: " inferior-lisp-program) - inferior-lisp-program))) - (if (not (comint-check-proc "*inferior-lisp*")) - (let ((cmdlist (inferior-lisp-args-to-list cmd))) - (set-buffer (apply (function make-comint) - "inferior-lisp" (car cmdlist) nil (cdr cmdlist))) - (inferior-lisp-mode))) - (setq inferior-lisp-buffer "*inferior-lisp*") - (pop-to-buffer "*inferior-lisp*")) -;;;###autoload (add-hook 'same-window-buffer-names "*inferior-lisp*") - -;;;jwz: ilisp is better, don't ###autoload -(define-function 'run-lisp 'inferior-lisp) - -;;; Break a string up into a list of arguments. -;;; This will break if you have an argument with whitespace, as in -;;; string = "-ab +c -x 'you lose'". -(defun inferior-lisp-args-to-list (string) - (let ((where (string-match "[ \t]" string))) - (cond ((null where) (list string)) - ((not (= where 0)) - (cons (substring string 0 where) - (inferior-lisp-args-to-list (substring string (+ 1 where) - (length string))))) - (t (let ((pos (string-match "[^ \t]" string))) - (if (null pos) - nil - (inferior-lisp-args-to-list (substring string pos - (length string))))))))) - -(defun lisp-eval-region (start end &optional and-go) - "Send the current region to the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "r\nP") - (comint-send-region (inferior-lisp-proc) start end) - (comint-send-string (inferior-lisp-proc) "\n") - (if and-go (switch-to-lisp t))) - -(defun lisp-eval-defun (&optional and-go) - "Send the current defun to the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "P") - (save-excursion - (end-of-defun) - (skip-chars-backward " \t\n\r\f") ; Makes allegro happy - (let ((end (point))) - (beginning-of-defun) - (lisp-eval-region (point) end))) - (if and-go (switch-to-lisp t))) - -(defun lisp-eval-last-sexp (&optional and-go) - "Send the previous sexp to the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "P") - (lisp-eval-region (save-excursion (backward-sexp) (point)) (point) and-go)) - -;;; Common Lisp COMPILE sux. -(defun lisp-compile-region (start end &optional and-go) - "Compile the current region in the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "r\nP") - (comint-send-string - (inferior-lisp-proc) - (format "(funcall (compile nil `(lambda () (progn 'compile %s))))\n" - (buffer-substring start end))) - (if and-go (switch-to-lisp t))) - -(defun lisp-compile-defun (&optional and-go) - "Compile the current defun in the inferior Lisp process. -Prefix argument means switch to the Lisp buffer afterwards." - (interactive "P") - (save-excursion - (end-of-defun) - (skip-chars-backward " \t\n\r\f") ; Makes allegro happy - (let ((e (point))) - (beginning-of-defun) - (lisp-compile-region (point) e))) - (if and-go (switch-to-lisp t))) - -(defun switch-to-lisp (eob-p) - "Switch to the inferior Lisp process buffer. -With argument, positions cursor at end of buffer." - (interactive "P") - (if (get-buffer inferior-lisp-buffer) - (pop-to-buffer inferior-lisp-buffer) - (error "No current inferior Lisp buffer")) - (cond (eob-p - (push-mark) - (goto-char (point-max))))) - - -;;; Now that lisp-compile/eval-defun/region takes an optional prefix arg, -;;; these commands are redundant. But they are kept around for the user -;;; to bind if he wishes, for backwards functionality, and because it's -;;; easier to type C-c e than C-u C-c C-e. - -(defun lisp-eval-region-and-go (start end) - "Send the current region to the inferior Lisp, and switch to its buffer." - (interactive "r") - (lisp-eval-region start end t)) - -(defun lisp-eval-defun-and-go () - "Send the current defun to the inferior Lisp, and switch to its buffer." - (interactive) - (lisp-eval-defun t)) - -(defun lisp-compile-region-and-go (start end) - "Compile the current region in the inferior Lisp, and switch to its buffer." - (interactive "r") - (lisp-compile-region start end t)) - -(defun lisp-compile-defun-and-go () - "Compile the current defun in the inferior Lisp, and switch to its buffer." - (interactive) - (lisp-compile-defun t)) - -;;; A version of the form in H. Shevis' soar-mode.el package. Less robust. -;;; (defun lisp-compile-sexp (start end) -;;; "Compile the s-expression bounded by START and END in the inferior lisp. -;;; If the sexp isn't a DEFUN form, it is evaluated instead." -;;; (cond ((looking-at "(defun\\s +") -;;; (goto-char (match-end 0)) -;;; (let ((name-start (point))) -;;; (forward-sexp 1) -;;; (process-send-string "inferior-lisp" -;;; (format "(compile '%s #'(lambda " -;;; (buffer-substring name-start -;;; (point))))) -;;; (let ((body-start (point))) -;;; (goto-char start) (forward-sexp 1) ; Can't use end-of-defun. -;;; (process-send-region "inferior-lisp" -;;; (buffer-substring body-start (point)))) -;;; (process-send-string "inferior-lisp" ")\n")) -;;; (t (lisp-eval-region start end))))) -;;; -;;; (defun lisp-compile-region (start end) -;;; "Each s-expression in the current region is compiled (if a DEFUN) -;;; or evaluated (if not) in the inferior lisp." -;;; (interactive "r") -;;; (save-excursion -;;; (goto-char start) (end-of-defun) (beginning-of-defun) ; error check -;;; (if (< (point) start) (error "region begins in middle of defun")) -;;; (goto-char start) -;;; (let ((s start)) -;;; (end-of-defun) -;;; (while (<= (point) end) ; Zip through -;;; (lisp-compile-sexp s (point)) ; compiling up defun-sized chunks. -;;; (setq s (point)) -;;; (end-of-defun)) -;;; (if (< s end) (lisp-compile-sexp s end))))) -;;; -;;; End of HS-style code - - -(defvar lisp-prev-l/c-dir/file nil - "Record last directory and file used in loading or compiling. -This holds a cons cell of the form `(DIRECTORY . FILE)' -describing the last `lisp-load-file' or `lisp-compile-file' command.") - -(defvar lisp-source-modes '(lisp-mode) - "*Used to determine if a buffer contains Lisp source code. -If it's loaded into a buffer that is in one of these major modes, it's -considered a Lisp source file by `lisp-load-file' and `lisp-compile-file'. -Used by these commands to determine defaults.") - -(defun lisp-load-file (file-name) - "Load a Lisp file into the inferior Lisp process." - (interactive (comint-get-source "Load Lisp file: " lisp-prev-l/c-dir/file - lisp-source-modes nil)) ; NIL because LOAD - ; doesn't need an exact name - (comint-check-source file-name) ; Check to see if buffer needs saved. - (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name) - (file-name-nondirectory file-name))) - (comint-send-string (inferior-lisp-proc) - (format inferior-lisp-load-command file-name)) - (switch-to-lisp t)) - -(defun lisp-compile-file (file-name) - "Compile a Lisp file in the inferior Lisp process." - (interactive (comint-get-source "Compile Lisp file: " lisp-prev-l/c-dir/file - lisp-source-modes nil)) ; NIL = don't need - ; suffix .lisp - (comint-check-source file-name) ; Check to see if buffer needs saved. - (setq lisp-prev-l/c-dir/file (cons (file-name-directory file-name) - (file-name-nondirectory file-name))) - (comint-send-string (inferior-lisp-proc) (concat "(compile-file \"" - file-name - "\"\)\n")) - (switch-to-lisp t)) - - - -;;; Documentation functions: function doc, var doc, arglist, and -;;; describe symbol. -;;; =========================================================================== - -;;; Command strings -;;; =============== - -(defvar lisp-function-doc-command - "(let ((fn '%s)) - (format t \"Documentation for ~a:~&~a\" - fn (documentation fn 'function)) - (values))\n" - "Command to query inferior Lisp for a function's documentation.") - -(defvar lisp-var-doc-command - "(let ((v '%s)) - (format t \"Documentation for ~a:~&~a\" - v (documentation v 'variable)) - (values))\n" - "Command to query inferior Lisp for a variable's documentation.") - -(defvar lisp-arglist-command - "(let ((fn '%s)) - (format t \"Arglist for ~a: ~a\" fn (arglist fn)) - (values))\n" - "Command to query inferior Lisp for a function's arglist.") - -(defvar lisp-describe-sym-command - "(describe '%s)\n" - "Command to query inferior Lisp for a variable's documentation.") - - -;;; Ancillary functions -;;; =================== - -;;; Reads a string from the user. -(defun lisp-symprompt (prompt default) - (list (let* ((prompt (if default - (format "%s (default %s): " prompt default) - (concat prompt ": "))) - (ans (read-string prompt))) - (if (zerop (length ans)) default ans)))) - - -;;; Adapted from function-called-at-point in help.el. -(defun lisp-fn-called-at-pt () - "Returns the name of the function called in the current call. -The value is nil if it can't find one." - (condition-case nil - (save-excursion - (save-restriction - (narrow-to-region (max (point-min) (- (point) 1000)) (point-max)) - (backward-up-list 1) - (forward-char 1) - (let ((obj (read (current-buffer)))) - (and (symbolp obj) obj)))) - (error nil))) - - -;;; Adapted from variable-at-point in help.el. -(defun lisp-var-at-pt () - (condition-case () - (save-excursion - (forward-sexp -1) - (skip-chars-forward "'") - (let ((obj (read (current-buffer)))) - (and (symbolp obj) obj))) - (error nil))) - - -;;; Documentation functions: fn and var doc, arglist, and symbol describe. -;;; ====================================================================== - -(defun lisp-show-function-documentation (fn) - "Send a command to the inferior Lisp to give documentation for function FN. -See variable `lisp-function-doc-command'." - (interactive (lisp-symprompt "Function doc" (lisp-fn-called-at-pt))) - (comint-proc-query (inferior-lisp-proc) - (format lisp-function-doc-command fn))) - -(defun lisp-show-variable-documentation (var) - "Send a command to the inferior Lisp to give documentation for function FN. -See variable `lisp-var-doc-command'." - (interactive (lisp-symprompt "Variable doc" (lisp-var-at-pt))) - (comint-proc-query (inferior-lisp-proc) (format lisp-var-doc-command var))) - -(defun lisp-show-arglist (fn) - "Send a query to the inferior Lisp for the arglist for function FN. -See variable `lisp-arglist-command'." - (interactive (lisp-symprompt "Arglist" (lisp-fn-called-at-pt))) - (comint-proc-query (inferior-lisp-proc) (format lisp-arglist-command fn))) - -(defun lisp-describe-sym (sym) - "Send a command to the inferior Lisp to describe symbol SYM. -See variable `lisp-describe-sym-command'." - (interactive (lisp-symprompt "Describe" (lisp-var-at-pt))) - (comint-proc-query (inferior-lisp-proc) - (format lisp-describe-sym-command sym))) - - -;; "Returns the current inferior Lisp process. -;; See variable `inferior-lisp-buffer'." -(defun inferior-lisp-proc () - (let ((proc (get-buffer-process (if (eq major-mode 'inferior-lisp-mode) - (current-buffer) - inferior-lisp-buffer)))) - (or proc - (error "No Lisp subprocess; see variable `inferior-lisp-buffer'")))) - - -;;; Do the user's customization... -;;;=============================== -(defvar inferior-lisp-load-hook nil - "This hook is run when the library `inf-lisp' is loaded. -This is a good place to put keybindings.") - -(run-hooks 'inferior-lisp-load-hook) - -;;; CHANGE LOG -;;; =========================================================================== -;;; 7/21/92 Jim Blandy -;;; - Changed all uses of the cmulisp name or prefix to inferior-lisp; -;;; this is now the official inferior lisp package. Use the global -;;; ChangeLog from now on. -;;; 5/24/90 Olin -;;; - Split cmulisp and cmushell modes into separate files. -;;; Not only is this a good idea, it's apparently the way it'll be rel 19. -;;; - Upgraded process sends to use comint-send-string instead of -;;; process-send-string. -;;; - Explicit references to process "cmulisp" have been replaced with -;;; (cmulisp-proc). This allows better handling of multiple process bufs. -;;; - Added process query and var/function/symbol documentation -;;; commands. Based on code written by Douglas Roberts. -;;; - Added lisp-eval-last-sexp, bound to C-x C-e. -;;; -;;; 9/20/90 Olin -;;; Added a save-restriction to lisp-fn-called-at-pt. This bug and fix -;;; reported by Lennart Staflin. -;;; -;;; 3/12/90 Olin -;;; - lisp-load-file and lisp-compile-file no longer switch-to-lisp. -;;; Tale suggested this. -;;; - Reversed this decision 7/15/91. You need the visual feedback. -;;; -;;; 7/25/91 Olin -;;; Changed all keybindings of the form C-c . These are -;;; supposed to be reserved for the user to bind. This affected -;;; mainly the compile/eval-defun/region[-and-go] commands. -;;; This was painful, but necessary to adhere to the gnumacs standard. -;;; For some backwards compatibility, see the -;;; cmulisp-install-letter-bindings -;;; function. -;;; -;;; 8/2/91 Olin -;;; - The lisp-compile/eval-defun/region commands now take a prefix arg, -;;; which means switch-to-lisp after sending the text to the Lisp process. -;;; This obsoletes all the -and-go commands. The -and-go commands are -;;; kept around for historical reasons, and because the user can bind -;;; them to key sequences shorter than C-u C-c C-. -;;; - If M-x cmulisp is invoked with a prefix arg, it allows you to -;;; edit the command line. - -(provide 'inf-lisp) - -;;; inf-lisp.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/kermit.el --- a/lisp/comint/kermit.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -;;; kermit.el --- additions to shell mode for use with kermit, etc. - -;; Copyright (C) 1988 Free Software Foundation, Inc. - -;; Author: Jeff Norden -;; Created: 15 Feb 1988 -;; Keywords: comm - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;; I'm not sure, but I think somebody asked about running kermit under shell -;; mode a while ago. Anyway, here is some code that I find useful. The result -;; is that I can log onto machines with primitive operating systems (VMS and -;; ATT system V :-), and still have the features of shell-mode available for -;; command history, etc. It's also handy to be able to run a file transfer in -;; an emacs window. The transfer is in the "background", but you can also -;; monitor or stop it easily. - -;; The ^\ key is bound to a function for sending escape sequences to kermit, -;; and ^C^Q can be used to send any control characters needed thru to the -;; system you connect to. A more serious problem is that some brain-dead -;; systems will not recognize a ^J as an end-of-line character. So LFD is -;; bound to a new function which acts just like CR usually does in shell-mode, -;; but a ^M is sent as an end-of-line. Functions are also provided to swap the -;; bindings of CR and LFD. I've also included a filter which will clean out -;; any ^M's or ^@'s that get typed at you, but I don't really recommend it. -;; There doesn't seem to be an acceptably fast way to do this via emacs-lisp. -;; Invoking kermit by the command " kermit | tr -d '\015' " seems to work -;; better (on my system anyway). - -;; Here's how I've been using this setup. We have several machines connected -;; thru a fairly stupid terminal switch. If I want to connect to unix system, -;; then I use the LFD key to talk to the switch, and ignore any ^M's in the -;; buffer, and do a " stty -echo nl " after I log in. Then the only real -;; difference from being in local shell-mode is that you need to type -;; ^C^Q^C to send an interrupt, and ^C^Q^Z for a stop signal, etc. (since ^C^C -;; just generates a local stop signal, which kermit ignores). -;; To connect to a VMS system, I use a shell script to invoke kermit thru the -;; tr filter, do "M-X kermit-send-cr", and then tell VMS that I'm on a -;; half-duplex terminal. - -;; Some caveats: -;; 1) Kermit under shell mode is a real pain if you don't have pty's. I -;; recently discovered this on our 3b2/400. When kermit can't find a tty, it -;; assumes it is supposed to be in remote mode. So the simple command "kermit" -;; won't work in shell mode on such a system. You can get around this by using -;; the -c (connect) command line option, which means you also have to specify a -;; line and baud on the command line, as in "kermit -l /dev/tty53 -b 9600 -c". -;; However, this will cause kermit to exit when the connection is closed. So -;; in order to do a file transfer, you have to think ahead and add -r -;; (receive) to the command line. This means that you can't use the server -;; feature. The only fix I can see is to muck around with the source code for -;; kermit, although this probably wouldn't be too hard. What is needed is an -;; option to force kermit to be local, to use stdin and stdout for interactive -;; speech, and to forget about cbreak mode. - -;; Please let me know if any bugs turn up. -;; Feb 1988, Jeff Norden - jeff@colgate.csnet - -;;; Code: - -(require 'shell) - -(defvar kermit-esc-char "\C-\\" "*Kermit's escape char") - -(defun kermit-esc () - "For sending escape sequences to a kermit running in shell mode." - (interactive) - (process-send-string - (get-buffer-process (current-buffer)) - (concat kermit-esc-char (char-to-string (read-char))))) - -(defun kermit-send-char () - "Send an arbitrary character to a program in shell mode." - (interactive) - (process-send-string - (get-buffer-process (current-buffer)) - (char-to-string (read-char)))) - -(define-key shell-mode-map "\C-\\" 'kermit-esc) -(define-key shell-mode-map "\C-c\C-q" 'kermit-send-char) -;; extra bindings for folks suffering form ^S/^Q braindamage: -(define-key shell-mode-map "\C-c\\" 'kermit-esc) - -(defun kermit-send-input-cr () - "Like \\[comint-send-input] but end the line with carriage-return." - (interactive) - (comint-send-input) - (comint-send-string (get-buffer-process (current-buffer)) "\r")) - -;; This is backwards of what makes sense, but ... -(define-key shell-mode-map "\n" 'kermit-send-input-cr) - -(defun kermit-default-cr () - "Make RETURN end the line with carriage-return and LFD end it with a newline. -This is useful for talking to other systems on which carriage-return -is the normal way to end a line." - (interactive) - (define-key shell-mode-map "\r" 'kermit-send-input-cr) - (define-key shell-mode-map "\n" 'comint-send-input)) - -(defun kermit-default-nl () - "Make RETURN end the line with a newline char. This is the default state. -In this state, use LFD to send a line and end it with a carriage-return." - (interactive) - (define-key shell-mode-map "\n" 'kermit-send-input-cr) - (define-key shell-mode-map "\r" 'comint-send-input)) - -(defun kermit-clean-filter (proc str) - "Strip ^M and ^@ characters from process output." - (save-excursion - (let ((beg (process-mark proc))) - (set-buffer (process-buffer proc)) - (goto-char beg) - (insert-before-markers str) - (while (re-search-backward "[\r\C-a]+" beg t) - (replace-match ""))))) - -(defun kermit-clean-on () - "Delete all null characters and ^M's from the kermit output. -Note that another (perhaps better) way to do this is to use the -command `kermit | tr -d '\\015''." - (interactive) - (set-process-filter (get-buffer-process (current-buffer)) - 'kermit-clean-filter)) - -(defun kermit-clean-off () - "Cancel a previous kermit-clean-shell-on command." - (interactive) - (set-process-filter (get-buffer-process (current-buffer)) nil)) - -;;; kermit.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/rlogin.el --- a/lisp/comint/rlogin.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,341 +0,0 @@ -;;; rlogin.el --- remote login interface - -;; Author: Noah Friedman -;; Maintainer: Noah Friedman -;; Keywords: unix, comm - -;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. -;; -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this program; if not, write to: The Free Software Foundation, -;; Inc.; 675 Massachusetts Avenue.; Cambridge, MA 02139, USA. - -;; $Id: rlogin.el,v 1.2 1997/04/19 23:20:49 steve Exp $ - -;;; Commentary: - -;; Support for remote logins using `rlogin'. -;; This program is layered on top of shell.el; the code here only accounts -;; for the variations needed to handle a remote process, e.g. directory -;; tracking and the sending of some special characters. - -;; If you wish for rlogin mode to prompt you in the minibuffer for -;; passwords when a password prompt appears, just enter m-x send-invisible -;; and type in your line, or add `comint-watch-for-password-prompt' to -;; `comint-output-filter-functions'. - -;;; Code: - -(require 'comint) -(require 'shell) - -(defgroup rlogin nil - "Remote login interface" - :group 'processes - :group 'unix) - - -(defcustom rlogin-program "rlogin" - "*Name of program to invoke rlogin" - :type 'string - :group 'rlogin) - -(defcustom rlogin-explicit-args nil - "*List of arguments to pass to rlogin on the command line." - :type '(repeat (string :tag "Argument")) - :group 'rlogin) - -(defcustom rlogin-mode-hook nil - "*Hooks to run after setting current buffer to rlogin-mode." - :type 'hook - :group 'rlogin) - -(defcustom rlogin-process-connection-type nil - "*If non-`nil', use a pty for the local rlogin process. -If `nil', use a pipe (if pipes are supported on the local system). - -Generally it is better not to waste ptys on systems which have a static -number of them. On the other hand, some implementations of `rlogin' assume -a pty is being used, and errors will result from using a pipe instead." - :type '(choice (const :tag "ptys" t) - (const :tag "pipes" nil)) - :group 'rlogin) - -(defcustom rlogin-directory-tracking-mode 'local - "*Control whether and how to do directory tracking in an rlogin buffer. - -nil means don't do directory tracking. - -t means do so using an ftp remote file name. - -Any other value means do directory tracking using local file names. -This works only if the remote machine and the local one -share the same directories (through NFS). This is the default. - -This variable becomes local to a buffer when set in any fashion for it. - -It is better to use the function of the same name to change the behavior of -directory tracking in an rlogin session once it has begun, rather than -simply setting this variable, since the function does the necessary -re-synching of directories." - :type '(choice (const :tag "off" nil) - (const :tag "ftp" t) - (const :tag "local" local)) - :group 'rlogin) - -(make-variable-buffer-local 'rlogin-directory-tracking-mode) - -(defcustom rlogin-host nil - "*The name of the remote host. This variable is buffer-local." - :type '(choice (const nil) string) - :group 'rlogin) - -(defcustom rlogin-remote-user nil - "*The username used on the remote host. -This variable is buffer-local and defaults to your local user name. -If rlogin is invoked with the `-l' option to specify the remote username, -this variable is set from that." - :type '(choice (const nil) string) - :group 'rlogin) - -;; Initialize rlogin mode map. -(defvar rlogin-mode-map '()) -(cond - ((null rlogin-mode-map) - (setq rlogin-mode-map (if (consp shell-mode-map) - (cons 'keymap shell-mode-map) - (copy-keymap shell-mode-map))) - (define-key rlogin-mode-map "\C-c\C-c" 'rlogin-send-Ctrl-C) - (define-key rlogin-mode-map "\C-c\C-d" 'rlogin-send-Ctrl-D) - (define-key rlogin-mode-map "\C-c\C-z" 'rlogin-send-Ctrl-Z) - (define-key rlogin-mode-map "\C-c\C-\\" 'rlogin-send-Ctrl-backslash) - (define-key rlogin-mode-map "\C-d" 'rlogin-delchar-or-send-Ctrl-D) - (define-key rlogin-mode-map "\C-i" 'rlogin-tab-or-complete))) - - -;;;###autoload (add-hook 'same-window-regexps "^\\*rlogin-.*\\*\\(\\|<[0-9]+>\\)") - -(defvar rlogin-history nil) - -;;;###autoload -(defun rlogin (input-args &optional buffer) - "Open a network login connection to HOST via the `rlogin' program. -Input is sent line-at-a-time to the remote connection. - -Communication with the remote host is recorded in a buffer `*rlogin-HOST*' -\(or `*rlogin-USER@HOST*' if the remote username differs\). -If a prefix argument is given and the buffer `*rlogin-HOST*' already exists, -a new buffer with a different connection will be made. - -When called from a program, if the optional second argument is a string or -buffer, it names the buffer to use. - -The variable `rlogin-program' contains the name of the actual program to -run. It can be a relative or absolute path. - -The variable `rlogin-explicit-args' is a list of arguments to give to -the rlogin when starting. They are added after any arguments given in -INPUT-ARGS. - -If the default value of `rlogin-directory-tracking-mode' is t, then the -default directory in that buffer is set to a remote (FTP) file name to -access your home directory on the remote machine. Occasionally this causes -an error, if you cannot access the home directory on that machine. This -error is harmless as long as you don't try to use that default directory. - -If `rlogin-directory-tracking-mode' is neither t nor nil, then the default -directory is initially set up to your (local) home directory. -This is useful if the remote machine and your local machine -share the same files via NFS. This is the default. - -If you wish to change directory tracking styles during a session, use the -function `rlogin-directory-tracking-mode' rather than simply setting the -variable." - (interactive (list - (read-from-minibuffer "rlogin arguments (hostname first): " - nil nil nil 'rlogin-history) - current-prefix-arg)) - - (let* ((process-connection-type rlogin-process-connection-type) - (args (if rlogin-explicit-args - (append (rlogin-parse-words input-args) - rlogin-explicit-args) - (rlogin-parse-words input-args))) - (host (car args)) - (user (or (car (cdr (member "-l" args))) - (user-login-name))) - (buffer-name (if (string= user (user-login-name)) - (format "*rlogin-%s*" host) - (format "*rlogin-%s@%s*" user host))) - proc) - - (cond ((null buffer)) - ((or (stringp buffer) (bufferp buffer)) - (setq buffer-name buffer)) - ((numberp buffer) - (setq buffer-name (format "%s<%d>" buffer-name buffer))) - (t - (setq buffer-name (generate-new-buffer-name buffer-name)))) - - (pop-to-buffer buffer-name) - (cond - ((comint-check-proc buffer-name)) - (t - (comint-exec (current-buffer) buffer-name rlogin-program nil args) - (setq proc (get-process buffer-name)) - ;; Set process-mark to point-max in case there is text in the - ;; buffer from a previous exited process. - (set-marker (process-mark proc) (point-max)) - (rlogin-mode) - - ;; comint-output-filter-functions is just like a hook, except that the - ;; functions in that list are passed arguments. add-hook serves well - ;; enough for modifying it. - (add-hook 'comint-output-filter-functions 'rlogin-carriage-filter) - - (make-local-variable 'rlogin-host) - (setq rlogin-host host) - (make-local-variable 'rlogin-remote-user) - (setq rlogin-remote-user user) - - (cond - ((eq rlogin-directory-tracking-mode t) - ;; Do this here, rather than calling the tracking mode function, to - ;; avoid a gratuitous resync check; the default should be the - ;; user's home directory, be it local or remote. - (setq comint-file-name-prefix - (concat "/" rlogin-remote-user "@" rlogin-host ":")) - (cd-absolute comint-file-name-prefix)) - ((null rlogin-directory-tracking-mode)) - (t - (cd-absolute (concat comint-file-name-prefix "~/")))))))) - -(defun rlogin-mode () - "Set major-mode for rlogin sessions. -If `rlogin-mode-hook' is set, run it." - (interactive) - (kill-all-local-variables) - (shell-mode) - (setq major-mode 'rlogin-mode) - (setq mode-name "rlogin") - (use-local-map rlogin-mode-map) - (setq shell-dirtrackp rlogin-directory-tracking-mode) - (make-local-variable 'comint-file-name-prefix) - (run-hooks 'rlogin-mode-hook)) - -(defun rlogin-directory-tracking-mode (&optional prefix) - "Do remote or local directory tracking, or disable entirely. - -If called with no prefix argument or a unspecified prefix argument (just -``\\[universal-argument]'' with no number) do remote directory tracking via -ange-ftp. If called as a function, give it no argument. - -If called with a negative prefix argument, disable directory tracking -entirely. - -If called with a positive, numeric prefix argument, e.g. -``\\[universal-argument] 1 M-x rlogin-directory-tracking-mode\'', -then do directory tracking but assume the remote filesystem is the same as -the local system. This only works in general if the remote machine and the -local one share the same directories (through NFS)." - (interactive "P") - (cond - ((or (null prefix) - (consp prefix)) - (setq rlogin-directory-tracking-mode t) - (setq shell-dirtrackp t) - (setq comint-file-name-prefix - (concat "/" rlogin-remote-user "@" rlogin-host ":"))) - ((< prefix 0) - (setq rlogin-directory-tracking-mode nil) - (setq shell-dirtrackp nil)) - (t - (setq rlogin-directory-tracking-mode 'local) - (setq comint-file-name-prefix "") - (setq shell-dirtrackp t))) - (cond - (shell-dirtrackp - (let* ((proc (get-buffer-process (current-buffer))) - (proc-mark (process-mark proc)) - (current-input (buffer-substring proc-mark (point-max))) - (orig-point (point)) - (offset (and (>= orig-point proc-mark) - (- (point-max) orig-point)))) - (unwind-protect - (progn - (delete-region proc-mark (point-max)) - (goto-char (point-max)) - (shell-resync-dirs)) - (goto-char proc-mark) - (insert current-input) - (if offset - (goto-char (- (point-max) offset)) - (goto-char orig-point))))))) - - -;; Parse a line into its constituent parts (words separated by -;; whitespace). Return a list of the words. -(defun rlogin-parse-words (line) - (let ((list nil) - (posn 0) - (match-data (match-data))) - (while (string-match "[^ \t\n]+" line posn) - (setq list (cons (substring line (match-beginning 0) (match-end 0)) - list)) - (setq posn (match-end 0))) - (store-match-data (match-data)) - (nreverse list))) - -(defun rlogin-carriage-filter (string) - (let* ((point-marker (point-marker)) - (end (process-mark (get-buffer-process (current-buffer)))) - (beg (or (and (boundp 'comint-last-output-start) - comint-last-output-start) - (- end (length string))))) - (goto-char beg) - (while (search-forward "\C-m" end t) - (delete-char -1)) - (goto-char point-marker))) - -(defun rlogin-send-Ctrl-C () - (interactive) - (send-string nil "\C-c")) - -(defun rlogin-send-Ctrl-D () - (interactive) - (send-string nil "\C-d")) - -(defun rlogin-send-Ctrl-Z () - (interactive) - (send-string nil "\C-z")) - -(defun rlogin-send-Ctrl-backslash () - (interactive) - (send-string nil "\C-\\")) - -(defun rlogin-delchar-or-send-Ctrl-D (arg) - "\ -Delete ARG characters forward, or send a C-d to process if at end of buffer." - (interactive "p") - (if (eobp) - (rlogin-send-Ctrl-D) - (delete-char arg))) - -(defun rlogin-tab-or-complete () - "Complete file name if doing directory tracking, or just insert TAB." - (interactive) - (if rlogin-directory-tracking-mode - (comint-dynamic-complete) - (insert "\C-i"))) - -;;; rlogin.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/shell.el --- a/lisp/comint/shell.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,971 +0,0 @@ -;;; shell.el --- specialized comint.el for running the shell. - -;; Copyright (C) 1988, 1993, 1994, 1995 Free Software Foundation, Inc. - -;; Author: Olin Shivers -;; Maintainer: Simon Marshall -;; Keywords: processes - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: FSF 19.30. - -;;; Commentary: - -;;; Please send me bug reports, bug fixes, and extensions, so that I can -;;; merge them into the master source. -;;; - Olin Shivers (shivers@cs.cmu.edu) -;;; - Simon Marshall (simon@gnu.ai.mit.edu) - -;;; This file defines a a shell-in-a-buffer package (shell mode) built -;;; on top of comint mode. This is actually cmushell with things -;;; renamed to replace its counterpart in Emacs 18. cmushell is more -;;; featureful, robust, and uniform than the Emacs 18 version. - -;;; Since this mode is built on top of the general command-interpreter-in- -;;; a-buffer mode (comint mode), it shares a common base functionality, -;;; and a common set of bindings, with all modes derived from comint mode. -;;; This makes these modes easier to use. - -;;; For documentation on the functionality provided by comint mode, and -;;; the hooks available for customising it, see the file comint.el. -;;; For further information on shell mode, see the comments below. - -;;; Needs fixin: -;;; When sending text from a source file to a subprocess, the process-mark can -;;; move off the window, so you can lose sight of the process interactions. -;;; Maybe I should ensure the process mark is in the window when I send -;;; text to the process? Switch selectable? - -;; YOUR .EMACS FILE -;;============================================================================= -;; Some suggestions for your .emacs file. -;; -;; ;; Define M-# to run some strange command: -;; (eval-after-load "shell" -;; '(define-key shell-mode-map "\M-#" 'shells-dynamic-spell)) - -;;; Brief Command Documentation: -;;;============================================================================ -;;; Comint Mode Commands: (common to shell and all comint-derived modes) -;;; -;;; m-p comint-previous-input Cycle backwards in input history -;;; m-n comint-next-input Cycle forwards -;;; m-r comint-previous-matching-input Previous input matching a regexp -;;; m-s comint-next-matching-input Next input that matches -;;; m-c-l comint-show-output Show last batch of process output -;;; return comint-send-input -;;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff. -;;; c-c c-a comint-bol Beginning of line; skip prompt -;;; c-c c-u comint-kill-input ^u -;;; c-c c-w backward-kill-word ^w -;;; c-c c-c comint-interrupt-subjob ^c -;;; c-c c-z comint-stop-subjob ^z -;;; c-c c-\ comint-quit-subjob ^\ -;;; c-c c-o comint-kill-output Delete last batch of process output -;;; c-c c-r comint-show-output Show last batch of process output -;;; c-c c-h comint-dynamic-list-input-ring List input history -;;; send-invisible Read line w/o echo & send to proc -;;; comint-continue-subjob Useful if you accidentally suspend -;;; top-level job -;;; comint-mode-hook is the comint mode hook. - -;;; Shell Mode Commands: -;;; shell Fires up the shell process -;;; tab comint-dynamic-complete Complete filename/command/history -;;; m-? comint-dynamic-list-filename-completions -;;; List completions in help buffer -;;; m-c-f shell-forward-command Forward a shell command -;;; m-c-b shell-backward-command Backward a shell command -;;; shell-resync-dirs Resync the buffer's dir stack -;;; dirtrack-toggle Turn dir tracking on/off -;;; comint-strip-ctrl-m Remove trailing ^Ms from output -;;; -;;; The shell mode hook is shell-mode-hook -;;; comint-prompt-regexp is initialised to shell-prompt-pattern, for backwards -;;; compatibility. - -;;; Read the rest of this file for more information. - -;;; Customization and Buffer Variables -;;; =========================================================================== -;;; - -;;; Code: - -(require 'comint) - -(defgroup shell nil - "Running shell from within Emacs buffers" - :group 'processes - :group 'unix) - -(defgroup shell-directories nil - "Directory support in shell mode" - :group 'shell) - -(defgroup shell-faces nil - "Faces in shell buffers" - :group 'shell) - -;;;###autoload -(defvar shell-prompt-pattern (purecopy "^[^#$%>\n]*[#$%>] *") - "Regexp to match prompts in the inferior shell. -Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well. -This variable is used to initialise `comint-prompt-regexp' in the -shell buffer. - -The pattern should probably not match more than one line. If it does, -shell-mode may become confused trying to distinguish prompt from input -on lines which don't start with a prompt. - -This is a fine thing to set in your `.emacs' file.") - -(defcustom shell-completion-fignore nil - "*List of suffixes to be disregarded during file/command completion. -This variable is used to initialize `comint-completion-fignore' in the shell -buffer. The default is nil, for compatibility with most shells. -Some people like (\"~\" \"#\" \"%\"). - -This is a fine thing to set in your `.emacs' file." - :type '(repeat (string :tag "Suffix")) - :group 'shell) - -;jwz: turned this off; it's way too broken. -(defvar shell-delimiter-argument-list nil ;'(?\| ?& ?< ?> ?\( ?\) ?\; - "List of characters to recognise as separate arguments. -This variable is used to initialize `comint-delimiter-argument-list' in the -shell buffer. The default is (?\\| ?& ?< ?> ?\\( ?\\) ?\\;). - -This is a fine thing to set in your `.emacs' file.") - -(defvar shell-file-name-quote-list - (append shell-delimiter-argument-list '(?\ ?\* ?\! ?\" ?\' ?\`)) - "List of characters to quote when in a file name. -This variable is used to initialize `comint-file-name-quote-list' in the -shell buffer. The default is (?\ ?\* ?\! ?\" ?\' ?\`) plus characters -in `shell-delimiter-argument-list'. - -This is a fine thing to set in your `.emacs' file.") - -(defvar shell-dynamic-complete-functions - '(comint-replace-by-expanded-history - shell-dynamic-complete-environment-variable - shell-dynamic-complete-command - shell-replace-by-expanded-directory - comint-dynamic-complete-filename) - "List of functions called to perform completion. -This variable is used to initialise `comint-dynamic-complete-functions' in the -shell buffer. - -This is a fine thing to set in your `.emacs' file.") - -(defcustom shell-command-regexp "[^;&|\n]+" - "*Regexp to match a single command within a pipeline. -This is used for directory tracking and does not do a perfect job." - :type 'regexp - :group 'shell) - -(defcustom shell-completion-execonly t - "*If non-nil, use executable files only for completion candidates. -This mirrors the optional behavior of tcsh. - -Detecting executability of files may slow command completion considerably." - :type 'boolean - :group 'shell) - -(defcustom shell-multiple-shells nil - "*If non-nil, each time shell mode is invoked, a new shell is made" - :type 'boolean - :group 'shell) - -(defcustom shell-popd-regexp "popd" - "*Regexp to match subshell commands equivalent to popd." - :type 'regexp - :group 'shell-directories) - -(defcustom shell-pushd-regexp "pushd" - "*Regexp to match subshell commands equivalent to pushd." - :type 'regexp - :group 'shell-directories) - -(defcustom shell-pushd-tohome nil - "*If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd). -This mirrors the optional behavior of tcsh." - :type 'boolean - :group 'shell-directories) - -(defcustom shell-pushd-dextract nil - "*If non-nil, make \"pushd +n\" pop the nth dir to the stack top. -This mirrors the optional behavior of tcsh." - :type 'boolean - :group 'shell-directories) - -(defcustom shell-pushd-dunique nil - "*If non-nil, make pushd only add unique directories to the stack. -This mirrors the optional behavior of tcsh." - :type 'boolean - :group 'shell-directories) - -(defcustom shell-cd-regexp "cd" - "*Regexp to match subshell commands equivalent to cd." - :type 'regexp - :group 'shell-directories) - -(defcustom explicit-shell-file-name nil - "*If non-nil, is file name to use for explicitly requested inferior shell." - :type '(choice (const :tag "None" nil) file) - :group 'shell) - -(defcustom explicit-csh-args - (if (eq system-type 'hpux) - ;; -T persuades HP's csh not to think it is smarter - ;; than us about what terminal modes to use. - '("-i" "-T") - '("-i")) - "*Args passed to inferior shell by M-x shell, if the shell is csh. -Value is a list of strings, which may be nil." - :type '(repeat (string :tag "Argument")) - :group 'shell) - -(defcustom shell-input-autoexpand 'history - "*If non-nil, expand input command history references on completion. -This mirrors the optional behavior of tcsh (its autoexpand and histlit). - -If the value is `input', then the expansion is seen on input. -If the value is `history', then the expansion is only when inserting -into the buffer's input ring. See also `comint-magic-space' and -`comint-dynamic-complete'. - -This variable supplies a default for `comint-input-autoexpand', -for Shell mode only." - :type '(choice (const nil) (const input) (const history)) - :type 'shell) - -(defvar shell-dirstack nil - "List of directories saved by pushd in this buffer's shell. -Thus, this does not include the shell's current directory.") - -(defvar shell-dirtrackp t - "Non-nil in a shell buffer means directory tracking is enabled.") - -(defvar shell-last-dir nil - "Keep track of last directory for ksh `cd -' command.") - -(defvar shell-dirstack-query nil - "Command used by `shell-resync-dirs' to query the shell.") - -(defvar shell-mode-map nil) -(if (not shell-mode-map) - (let ((map (make-keymap))) - (set-keymap-parents map (list comint-mode-map)) - (set-keymap-name map 'shell-mode-map) - (define-key map "\C-c\C-f" 'shell-forward-command) - (define-key map "\C-c\C-b" 'shell-backward-command) - (define-key map "\t" 'comint-dynamic-complete) - (define-key map "\M-?" 'comint-dynamic-list-filename-completions) - ;; XEmacs: this is a pretty common operation for those of us - ;; who use directory aliases ... someone shoot me if they - ;; don't like this binding. Another possibility is C-c C-s - ;; but that's way awkward. - ;; July-5-1997, Bang! -slb - #-infodock (define-key map "\M-\C-m" 'shell-resync-dirs) - (setq shell-mode-map map))) - -(defcustom shell-mode-hook nil - "*Hook for customising Shell mode." - :type 'hook - :group 'shell) - - -;; font-locking -(defcustom shell-prompt-face 'shell-prompt-face - "Face for shell prompts." - :type 'face - :group 'shell-faces) -(defcustom shell-option-face 'shell-option-face - "Face for command line options." - :type 'face - :group 'shell-faces) -(defcustom shell-output-face 'shell-output-face - "Face for generic shell output." - :type 'face - :group 'shell-faces) -(defcustom shell-output-2-face 'shell-output-2-face - "Face for grep-like output." - :type 'face - :group 'shell-faces) -(defcustom shell-output-3-face 'shell-output-3-face - "Face for [N] output where N is a number." - :type 'face - :group 'shell-faces) - -(make-face shell-prompt-face) -(make-face shell-option-face) -(make-face shell-output-face) -(make-face shell-output-2-face) -(make-face shell-output-3-face) - -(defun shell-font-lock-mode-hook () - (or (face-differs-from-default-p shell-prompt-face) - (copy-face 'font-lock-keyword-face shell-prompt-face)) - (or (face-differs-from-default-p shell-option-face) - (copy-face 'font-lock-comment-face shell-option-face)) - (or (face-differs-from-default-p shell-output-face) - (copy-face 'italic shell-output-face)) - (or (face-differs-from-default-p shell-output-2-face) - (copy-face 'font-lock-string-face shell-output-2-face)) - (or (face-differs-from-default-p shell-output-3-face) - (copy-face 'font-lock-string-face shell-output-3-face)) - ;; we only need to do this once - (remove-hook 'font-lock-mode-hook 'shell-font-lock-mode-hook)) -(add-hook 'font-lock-mode-hook 'shell-font-lock-mode-hook) - -(defvar shell-prompt-pattern-for-font-lock nil - "If non-nil, pattern to use to font-lock the prompt. -When nil, shell-prompt-pattern will be used. Set this to a regular -expression if you want the font-locked pattern to be different then -the shell's prompt pattern.") - -(defvar shell-font-lock-keywords - (list '(eval . (cons (if shell-prompt-pattern-for-font-lock - shell-prompt-pattern-for-font-lock - shell-prompt-pattern) - shell-prompt-face)) - '("[ \t]\\([+-][^ \t\n>]+\\)" 1 shell-option-face) - '("^[^ \t\n]+:.*" . shell-output-2-face) - '("^\\[[1-9][0-9]*\\]" . shell-output-3-face) - '("^[^\n]+.*$" . shell-output-face)) - "Additional expressions to highlight in Shell mode.") -(put 'shell-mode 'font-lock-defaults '(shell-font-lock-keywords t)) - - -;;; Basic Procedures -;;; =========================================================================== -;;; - -(defun shell-mode () - "Major mode for interacting with an inferior shell. -\\\\[comint-send-input] after the end of the process' output sends the text from - the end of process to the end of the current line. -\\[comint-send-input] before end of process output copies the current line minus the - prompt to the end of the buffer and sends it (\\[comint-copy-old-input] just copies - the current line). -\\[send-invisible] reads a line of text without echoing it, and sends it to - the shell. This is useful for entering passwords. Or, add the function - `comint-watch-for-password-prompt' to `comint-output-filter-functions'. - -If you want to make multiple shell buffers, rename the `*shell*' buffer -using \\[rename-buffer] or \\[rename-uniquely] and start a new shell. - -If you want to make shell buffers limited in length, add the function -`comint-truncate-buffer' to `comint-output-filter-functions'. - -If you accidentally suspend your process, use \\[comint-continue-subjob] -to continue it. - -`cd', `pushd' and `popd' commands given to the shell are watched by Emacs to -keep this buffer's default directory the same as the shell's working directory. -While directory tracking is enabled, the shell's working directory is displayed -by \\[list-buffers] or \\[mouse-buffer-menu] in the `File' field. -\\[shell-resync-dirs] queries the shell and resyncs Emacs' idea of what the - current directory stack is. -\\[shell-dirtrack-toggle] turns directory tracking on and off. - -\\{shell-mode-map} -Customization: Entry to this mode runs the hooks on `comint-mode-hook' and -`shell-mode-hook' (in that order). Before each input, the hooks on -`comint-input-filter-functions' are run. After each shell output, the hooks -on `comint-output-filter-functions' are run. - -Variable `shell-multiple-shells' will automatically generate a new shell each -time it is invoked. - -Variables `shell-cd-regexp', `shell-pushd-regexp' and `shell-popd-regexp' -are used to match their respective commands, while `shell-pushd-tohome', -`shell-pushd-dextract' and `shell-pushd-dunique' control the behavior of the -relevant command. - -Variables `comint-completion-autolist', `comint-completion-addsuffix', -`comint-completion-recexact' and `comint-completion-fignore' control the -behavior of file name, command name and variable name completion. Variable -`shell-completion-execonly' controls the behavior of command name completion. -Variable `shell-completion-fignore' is used to initialise the value of -`comint-completion-fignore'. - -Variables `comint-input-ring-file-name' and `comint-input-autoexpand' control -the initialisation of the input ring history, and history expansion. - -Variables `comint-output-filter-functions', a hook, and -`comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output' -control whether input and output cause the window to scroll to the end of the -buffer." - (interactive) - (comint-mode) - (setq major-mode 'shell-mode) - (setq mode-name "Shell") - (use-local-map shell-mode-map) - (make-local-variable 'comint-prompt-regexp) - (setq comint-prompt-regexp shell-prompt-pattern) - (setq comint-completion-fignore shell-completion-fignore) - (make-local-variable 'comint-delimiter-argument-list) - (setq comint-delimiter-argument-list shell-delimiter-argument-list) - (make-local-variable 'comint-after-partial-filename-command) - (setq comint-after-partial-filename-command 'shell-after-partial-filename) - (make-local-variable 'comint-get-current-command) - (setq comint-get-current-command 'shell-get-current-command) - (make-local-variable 'comint-dynamic-complete-command-command) - (setq comint-dynamic-complete-command-command 'shell-dynamic-complete-command) - (setq comint-file-name-quote-list shell-file-name-quote-list) - (setq comint-dynamic-complete-functions shell-dynamic-complete-functions) - (make-local-variable 'paragraph-start) - (setq paragraph-start comint-prompt-regexp) - (make-local-variable 'shell-dirstack) - (setq shell-dirstack nil) - (make-local-variable 'shell-last-dir) - (setq shell-last-dir nil) - (make-local-variable 'shell-dirtrackp) - (setq shell-dirtrackp t) - (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t) - (setq comint-input-autoexpand shell-input-autoexpand) - (make-local-variable 'list-buffers-directory) - (setq list-buffers-directory (expand-file-name default-directory)) - ;; shell-dependent assignments. - (let ((shell (file-name-nondirectory (car - (process-command (get-buffer-process (current-buffer))))))) - (setq comint-input-ring-file-name - (or (getenv "HISTFILE") - (cond ((string-equal shell "bash") "~/.bash_history") - ((string-equal shell "ksh") "~/.sh_history") - (t "~/.history")))) - (if (or (equal comint-input-ring-file-name "") - (equal (file-truename comint-input-ring-file-name) "/dev/null")) - (setq comint-input-ring-file-name nil)) - (setq shell-dirstack-query - (if (string-match "^k?sh$" shell) "pwd" "dirs"))) - (run-hooks 'shell-mode-hook) - (comint-read-input-ring t) - (shell-dirstack-message)) - - -;;;###autoload -(defun shell () - "Run an inferior shell, with I/O through buffer *shell*. -If buffer exists but shell process is not running, make new shell. -If buffer exists and shell process is running, - just switch to buffer `*shell*'. -Program used comes from variable `explicit-shell-file-name', - or (if that is nil) from the ESHELL environment variable, - or else from SHELL if there is no ESHELL. -If a file `~/.emacs_SHELLNAME' exists, it is given as initial input - (Note that this may lose due to a timing error if the shell - discards input when it starts up.) -The buffer is put in Shell mode, giving commands for sending input -and controlling the subjobs of the shell. See `shell-mode'. -See also the variable `shell-prompt-pattern'. - -The shell file name (sans directories) is used to make a symbol name -such as `explicit-csh-args'. If that symbol is a variable, -its value is used as a list of arguments when invoking the shell. -Otherwise, one argument `-i' is passed to the shell. - -\(Type \\[describe-mode] in the shell buffer for a list of commands.)" - (interactive) - (let ((buffer "*shell*") - (buffer-name (if shell-multiple-shells - "*shell*" - "shell"))) - (cond ((or shell-multiple-shells - (not (comint-check-proc buffer))) - (let* ((prog (or explicit-shell-file-name - (getenv "ESHELL") - (getenv "SHELL") - "/bin/sh")) - (name (file-name-nondirectory prog)) - (startfile (concat "~/.emacs_" name)) - (xargs-name (intern-soft (concat "explicit-" name "-args")))) - (setq buffer (set-buffer (apply 'make-comint buffer-name prog - (if (file-exists-p startfile) - startfile) - (if (and xargs-name - (boundp xargs-name)) - (symbol-value xargs-name) - '("-i"))))) - (shell-mode)))) - (pop-to-buffer buffer) - (if shell-multiple-shells - (rename-buffer (generate-new-buffer-name "*shell*"))) - )) - -;;; Don't do this when shell.el is loaded, only while dumping. -;;;###autoload (add-hook 'same-window-buffer-names "*shell*") - -;;; Directory tracking -;;; =========================================================================== -;;; This code provides the shell mode input sentinel -;;; SHELL-DIRECTORY-TRACKER -;;; that tracks cd, pushd, and popd commands issued to the shell, and -;;; changes the current directory of the shell buffer accordingly. -;;; -;;; This is basically a fragile hack, although it's more accurate than -;;; the version in Emacs 18's shell.el. It has the following failings: -;;; 1. It doesn't know about the cdpath shell variable. -;;; 2. It cannot infallibly deal with command sequences, though it does well -;;; with these and with ignoring commands forked in another shell with ()s. -;;; 3. More generally, any complex command is going to throw it. Otherwise, -;;; you'd have to build an entire shell interpreter in emacs lisp. Failing -;;; that, there's no way to catch shell commands where cd's are buried -;;; inside conditional expressions, aliases, and so forth. -;;; -;;; The whole approach is a crock. Shell aliases mess it up. File sourcing -;;; messes it up. You run other processes under the shell; these each have -;;; separate working directories, and some have commands for manipulating -;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have -;;; commands that do *not* affect the current w.d. at all, but look like they -;;; do (e.g., the cd command in ftp). In shells that allow you job -;;; control, you can switch between jobs, all having different w.d.'s. So -;;; simply saying %3 can shift your w.d.. -;;; -;;; The solution is to relax, not stress out about it, and settle for -;;; a hack that works pretty well in typical circumstances. Remember -;;; that a half-assed solution is more in keeping with the spirit of Unix, -;;; anyway. Blech. -;;; -;;; One good hack not implemented here for users of programmable shells -;;; is to program up the shell w.d. manipulation commands to output -;;; a coded command sequence to the tty. Something like -;;; ESC | | -;;; where is the new current working directory. Then trash the -;;; directory tracking machinery currently used in this package, and -;;; replace it with a process filter that watches for and strips out -;;; these messages. - -(defun shell-directory-tracker (str) - "Tracks cd, pushd and popd commands issued to the shell. -This function is called on each input passed to the shell. -It watches for cd, pushd and popd commands and sets the buffer's -default directory to track these commands. - -You may toggle this tracking on and off with \\[shell-dirtrack-toggle]. -If emacs gets confused, you can resync with the shell -with \\[shell-resync-dirs]. - -See variables `shell-cd-regexp', `shell-pushd-regexp', and `shell-popd-regexp', -while `shell-pushd-tohome', `shell-pushd-dextract' and `shell-pushd-dunique' -control the behavior of the relevant command. - -Environment variables are expanded, see function `substitute-in-file-name'." - (if shell-dirtrackp - ;; We fail gracefully if we think the command will fail in the shell. - (condition-case err - (let ((start (progn (string-match "^[; \t]*" str) ; skip whitespace - (match-end 0))) - end cmd arg1) - (while (string-match shell-command-regexp str start) - (setq end (match-end 0) - cmd (comint-arguments (substring str start end) 0 0) - arg1 (comint-arguments (substring str start end) 1 1)) - (cond ((string-match (concat "\\`\\(" shell-popd-regexp - "\\)\\($\\|[ \t]\\)") - cmd) - (shell-process-popd (substitute-in-file-name arg1))) - ((string-match (concat "\\`\\(" shell-pushd-regexp - "\\)\\($\\|[ \t]\\)") - cmd) - (shell-process-pushd (substitute-in-file-name arg1))) - ((string-match (concat "\\`\\(" shell-cd-regexp - "\\)\\($\\|[ \t]\\)") - cmd) - (shell-process-cd (substitute-in-file-name arg1)))) - (setq start (progn (string-match "[; \t]*" str end) ; skip again - (match-end 0))))) - (error - ;; XEmacs change - (message nil) - (display-error err t))))) - -;; Like `cd', but prepends comint-file-name-prefix to absolute names. -(defun shell-cd-1 (dir dirstack) - (if shell-dirtrackp - (setq list-buffers-directory (file-name-as-directory - (expand-file-name dir)))) - (condition-case nil - (progn (if (file-name-absolute-p dir) - (cd-absolute (concat comint-file-name-prefix dir)) - (cd dir)) - (setq shell-dirstack dirstack) - (shell-dirstack-message)) - (file-error (message "Couldn't cd.")))) - -;;; popd [+n] -(defun shell-process-popd (arg) - (let ((num (or (shell-extract-num arg) 0))) - (cond ((and num (= num 0) shell-dirstack) - (shell-cd-1 (car shell-dirstack) (cdr shell-dirstack))) - ((and num (> num 0) (<= num (length shell-dirstack))) - (let* ((ds (cons nil shell-dirstack)) - (cell (nthcdr (1- num) ds))) - (rplacd cell (cdr (cdr cell))) - (setq shell-dirstack (cdr ds)) - (shell-dirstack-message))) - (t - (error "Couldn't popd"))))) - -;; Return DIR prefixed with comint-file-name-prefix as appropriate. -(defun shell-prefixed-directory-name (dir) - (if (= (length comint-file-name-prefix) 0) - dir - (if (file-name-absolute-p dir) - ;; The name is absolute, so prepend the prefix. - (concat comint-file-name-prefix dir) - ;; For relative name we assume default-directory already has the prefix. - (expand-file-name dir)))) - -;;; cd [dir] -(defun shell-process-cd (arg) - (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix - "~")) - ((string-equal "-" arg) shell-last-dir) - (t (shell-prefixed-directory-name arg))))) - (setq shell-last-dir default-directory) - (shell-cd-1 new-dir shell-dirstack))) - -;;; pushd [+n | dir] -(defun shell-process-pushd (arg) - (let ((num (shell-extract-num arg))) - (cond ((zerop (length arg)) - ;; no arg -- swap pwd and car of stack unless shell-pushd-tohome - (cond (shell-pushd-tohome - (shell-process-pushd (concat comint-file-name-prefix "~"))) - (shell-dirstack - (let ((old default-directory)) - (shell-cd-1 (car shell-dirstack) - (cons old (cdr shell-dirstack))))) - (t - (message "Directory stack empty.")))) - ((numberp num) - ;; pushd +n - (cond ((> num (length shell-dirstack)) - (message "Directory stack not that deep.")) - ((= num 0) - (error (message "Couldn't cd."))) - (shell-pushd-dextract - (let ((dir (nth (1- num) shell-dirstack))) - (shell-process-popd arg) - (shell-process-pushd default-directory) - (shell-cd-1 dir shell-dirstack))) - (t - (let* ((ds (cons default-directory shell-dirstack)) - (dslen (length ds)) - (front (nthcdr num ds)) - (back (reverse (nthcdr (- dslen num) (reverse ds)))) - (new-ds (append front back))) - (shell-cd-1 (car new-ds) (cdr new-ds)))))) - (t - ;; pushd - (let ((old-wd default-directory)) - (shell-cd-1 (shell-prefixed-directory-name arg) - (if (or (null shell-pushd-dunique) - (not (member old-wd shell-dirstack))) - (cons old-wd shell-dirstack) - shell-dirstack))))))) - -;; If STR is of the form +n, for n>0, return n. Otherwise, nil. -(defun shell-extract-num (str) - (and (string-match "^\\+[1-9][0-9]*$" str) - (string-to-int str))) - - -(defun shell-dirtrack-toggle () - "Turn directory tracking on and off in a shell buffer." - (interactive) - (if (setq shell-dirtrackp (not shell-dirtrackp)) - (setq list-buffers-directory default-directory) - (setq list-buffers-directory nil)) - (message "Directory tracking %s" (if shell-dirtrackp "ON" "OFF"))) - -;;; For your typing convenience: -;; XEmacs: removed this because then `M-x dir' doesn't complete to `dired' -;;(define-function 'dirtrack-toggle 'shell-dirtrack-toggle) - -(defun shell-cd (dir) - "Do normal `cd' to DIR, and set `list-buffers-directory'." - (if shell-dirtrackp - (setq list-buffers-directory (file-name-as-directory - (expand-file-name dir)))) - (cd dir)) - -(defun shell-resync-dirs () - "Resync the buffer's idea of the current directory stack. -This command queries the shell with the command bound to -`shell-dirstack-query' (default \"dirs\"), reads the next -line output and parses it to form the new directory stack. -DON'T issue this command unless the buffer is at a shell prompt. -Also, note that if some other subprocess decides to do output -immediately after the query, its output will be taken as the -new directory stack -- you lose. If this happens, just do the -command again." - (interactive) - (let* ((proc (get-buffer-process (current-buffer))) - (pmark (process-mark proc))) - (goto-char pmark) - (insert shell-dirstack-query) (insert "\n") - (sit-for 0) ; force redisplay - (comint-send-string proc shell-dirstack-query) - (comint-send-string proc "\n") - (set-marker pmark (point)) - (let ((pt (point))) ; wait for 1 line - ;; This extra newline prevents the user's pending input from spoofing us. - (insert "\n") (backward-char 1) - (while (not (looking-at ".+\n")) - (accept-process-output proc) - (goto-char pt) - ;; kludge to cope with shells that have "stty echo" turned on. - ;; of course this will lose if there is only one dir on the stack - ;; and it is named "dirs"... -jwz - (if (looking-at "^dirs\r?\n") (delete-region (point) (match-end 0))) - )) - (goto-char pmark) (delete-char 1) ; remove the extra newline - ;; That's the dirlist. grab it & parse it. - (let* ((dl (buffer-substring (match-beginning 0) (1- (match-end 0)))) - (dl-len (length dl)) - (ds '()) ; new dir stack - (i 0)) - (while (< i dl-len) - ;; regexp = optional whitespace, (non-whitespace), optional whitespace - (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir - (setq ds (cons (concat comint-file-name-prefix - (substring dl (match-beginning 1) - (match-end 1))) - ds)) - (setq i (match-end 0))) - (let ((ds (reverse ds))) - (shell-cd-1 (car ds) (cdr ds)))))) - -;;; For your typing convenience: -;; XEmacs: removed this because then `M-x dir' doesn't complete to `dired' -;(define-function 'dirs 'shell-resync-dirs) - -;; XEmacs addition -(defvar shell-dirstack-message-hook nil - "Hook to run after a cd, pushd or popd event") - -;;; Show the current dirstack on the message line. -;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo". -;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".) -;;; All the commands that mung the buffer's dirstack finish by calling -;;; this guy. -(defun shell-dirstack-message () - (let* ((msg "") - (ds (cons default-directory shell-dirstack)) - (home (format "^%s\\(/\\|$\\)" (regexp-quote (getenv "HOME")))) - (prefix (and comint-file-name-prefix - ;; XEmacs addition: don't turn "/foo" into "foo" !! - (not (= 0 (length comint-file-name-prefix))) - (format "^%s\\(/\\|$\\)" - (regexp-quote comint-file-name-prefix))))) - (while ds - (let ((dir (car ds))) - (if (string-match home dir) - (setq dir (concat "~/" (substring dir (match-end 0))))) - ;; Strip off comint-file-name-prefix if present. - (and prefix (string-match prefix dir) - (setq dir (substring dir (match-end 0))) - (setcar ds dir) - ) - (setq msg (concat msg dir " ")) - (setq ds (cdr ds)))) - ;; XEmacs change - (run-hooks 'shell-dirstack-message-hook) - (message msg))) - - -(defun shell-forward-command (&optional arg) - "Move forward across ARG shell command(s). Does not cross lines. -See `shell-command-regexp'." - (interactive "p") - (let ((limit (save-excursion (end-of-line nil) (point)))) - (if (re-search-forward (concat shell-command-regexp "\\([;&|][\t ]*\\)+") - limit 'move arg) - (skip-syntax-backward " ")))) - - -(defun shell-backward-command (&optional arg) - "Move backward across ARG shell command(s). Does not cross lines. -See `shell-command-regexp'." - (interactive "p") - (let ((limit (save-excursion (comint-bol nil) (point)))) - (if (> limit (point)) - (save-excursion (beginning-of-line) (setq limit (point)))) - (skip-syntax-backward " " limit) - (if (re-search-backward - (format "[;&|]+[\t ]*\\(%s\\)" shell-command-regexp) limit 'move arg) - (progn (goto-char (match-beginning 1)) - (skip-chars-forward ";&|"))))) - - -(defun shell-dynamic-complete-command () - "Dynamically complete the command at point. -This function is similar to `comint-dynamic-complete-filename', except that it -searches `exec-path' (minus the trailing emacs library path) for completion -candidates. Note that this may not be the same as the shell's idea of the -path. - -Completion is dependent on the value of `shell-completion-execonly', plus -those that effect file completion. See `shell-dynamic-complete-as-command'. - -Returns t if successful." - (interactive) - (let ((filename (comint-match-partial-filename))) - (if (and filename - (save-match-data (not (string-match "[~/]" filename))) - (eq (match-beginning 0) - (save-excursion (shell-backward-command 1) (point)))) - (prog2 (message "Completing command name...") - (shell-dynamic-complete-as-command))))) - - -(defun shell-dynamic-complete-as-command () - "Dynamically complete at point as a command. -See `shell-dynamic-complete-filename'. Returns t if successful." - (let* ((filename (or (comint-match-partial-filename) "")) - (pathnondir (file-name-nondirectory filename)) - (paths (cdr (reverse exec-path))) - (cwd (file-name-as-directory (expand-file-name default-directory))) - (ignored-extensions - (and comint-completion-fignore - (mapconcat (function (lambda (x) (concat (regexp-quote x) "$"))) - comint-completion-fignore "\\|"))) - (path "") (comps-in-path ()) (file "") (filepath "") (completions ())) - ;; Go thru each path in the search path, finding completions. - (while paths - (setq path (file-name-as-directory (comint-directory (or (car paths) "."))) - comps-in-path (and (file-accessible-directory-p path) - (file-name-all-completions pathnondir path))) - ;; Go thru each completion found, to see whether it should be used. - (while comps-in-path - (setq file (car comps-in-path) - filepath (concat path file)) - (if (and (not (member file completions)) - (not (and ignored-extensions - (string-match ignored-extensions file))) - (or (string-equal path cwd) - (not (file-directory-p filepath))) - (or (null shell-completion-execonly) - (file-executable-p filepath))) - (setq completions (cons file completions))) - (setq comps-in-path (cdr comps-in-path))) - (setq paths (cdr paths))) - ;; OK, we've got a list of completions. - (let ((success (let ((comint-completion-addsuffix nil)) - (comint-dynamic-simple-complete pathnondir completions)))) - (if (and (memq success '(sole shortest)) comint-completion-addsuffix - (not (file-directory-p (comint-match-partial-filename)))) - (insert " ")) - success))) - - -(defun shell-match-partial-variable () - "Return the variable at point, or nil if non is found." - (save-excursion - (let ((limit (point))) - (if (re-search-backward "[^A-Za-z0-9_{}]" nil 'move) - (or (looking-at "\\$") (forward-char 1))) - ;; Anchor the search forwards. - (if (or (eolp) (looking-at "[^A-Za-z0-9_{}$]")) - nil - (re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit) - (buffer-substring (match-beginning 0) (match-end 0)))))) - - -(defun shell-dynamic-complete-environment-variable () - "Dynamically complete the environment variable at point. -Completes if after a variable, i.e., if it starts with a \"$\". -See `shell-dynamic-complete-as-environment-variable'. - -This function is similar to `comint-dynamic-complete-filename', except that it -searches `process-environment' for completion candidates. Note that this may -not be the same as the interpreter's idea of variable names. The main problem -with this type of completion is that `process-environment' is the environment -which Emacs started with. Emacs does not track changes to the environment made -by the interpreter. Perhaps it would be more accurate if this function was -called `shell-dynamic-complete-process-environment-variable'. - -Returns non-nil if successful." - (interactive) - (let ((variable (shell-match-partial-variable))) - (if (and variable (string-match "^\\$" variable)) - (prog2 (message "Completing variable name...") - (shell-dynamic-complete-as-environment-variable))))) - - -(defun shell-dynamic-complete-as-environment-variable () - "Dynamically complete at point as an environment variable. -Used by `shell-dynamic-complete-environment-variable'. -Uses `comint-dynamic-simple-complete'." - (let* ((var (or (shell-match-partial-variable) "")) - (variable (substring var (or (string-match "[^$({]\\|$" var) 0))) - (variables (mapcar (function (lambda (x) - (substring x 0 (string-match "=" x)))) - process-environment)) - (addsuffix comint-completion-addsuffix) - (comint-completion-addsuffix nil) - (success (comint-dynamic-simple-complete variable variables))) - (if (memq success '(sole shortest)) - (let* ((var (shell-match-partial-variable)) - (variable (substring var (string-match "[^$({]" var))) - (protection (cond ((string-match "{" var) "}") - ((string-match "(" var) ")") - (t ""))) - (suffix (cond ((null addsuffix) "") - ((file-directory-p - (comint-directory (getenv variable))) "/") - (t " ")))) - (insert protection suffix))) - success)) - - -(defun shell-replace-by-expanded-directory () - "Expand directory stack reference before point. -Directory stack references are of the form \"=digit\" or \"=-\". -See `default-directory' and `shell-dirstack'. - -Returns t if successful." - (interactive) - (if (comint-match-partial-filename) - (save-excursion - (goto-char (match-beginning 0)) - (let ((stack (cons default-directory shell-dirstack)) - (index (cond ((looking-at "=-/?") - (length shell-dirstack)) - ((looking-at "=\\([0-9]+\\)") - (string-to-number - (buffer-substring - (match-beginning 1) (match-end 1))))))) - (cond ((null index) - nil) - ((>= index (length stack)) - (error "Directory stack not that deep.")) - (t - (replace-match (file-name-as-directory (nth index stack)) t t) - (message "Directory item: %d" index) - t)))))) - -(provide 'shell) - -;;; shell.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/ssh.el --- a/lisp/comint/ssh.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,358 +0,0 @@ -;;; ssh.el --- remote login interface - -;; Copyright (C) 1996, 1997 Noah S. Friedman - -;; Author: Noah Friedman -;; Maintainer: friedman@prep.ai.mit.edu -;; Keywords: unix, comm -;; Created: 1996-07-03 - -;; $Id: ssh.el,v 1.1 1997/05/28 16:30:50 steve Exp $ - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this program; if not, you can either send email to this -;; program's maintainer or write to: The Free Software Foundation, -;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. - -;;; Commentary: - -;; Support for remote logins using `ssh'. -;; This program is layered on top of shell.el; the code here only accounts -;; for the variations needed to handle a remote process, e.g. directory -;; tracking and the sending of some special characters. - -;; If you wish for ssh mode to prompt you in the minibuffer for -;; passwords when a password prompt appears, just enter m-x send-invisible -;; and type in your line, or add `comint-watch-for-password-prompt' to -;; `comint-output-filter-functions'. - -;;; Code: - -(require 'comint) -(require 'shell) - -(defgroup ssh nil - "Secure remote login interface" - :group 'processes - :group 'unix) - -(defcustom ssh-program "ssh" - "*Name of program to invoke ssh" - :type 'string - :group 'ssh) - -(defcustom ssh-explicit-args '() - "*List of arguments to pass to ssh on the command line." - :type '(repeat (string :tag "Argument")) - :group 'ssh) - -(defcustom ssh-mode-hook nil - "*Hooks to run after setting current buffer to ssh-mode." - :type 'hook - :group 'ssh) - -(defcustom ssh-process-connection-type t - "*If non-`nil', use a pty for the local ssh process. -If `nil', use a pipe (if pipes are supported on the local system). - -Generally it is better not to waste ptys on systems which have a static -number of them. However, ssh won't allocate a pty on the remote host -unless one is used locally as well." - :type '(choice (const :tag "ptys" t) - (const :tag "pipes" nil)) - :group 'ssh) - -(defcustom ssh-directory-tracking-mode 'local - "*Control whether and how to do directory tracking in an ssh buffer. - -nil means don't do directory tracking. - -t means do so using an ftp remote file name. - -Any other value means do directory tracking using local file names. -This works only if the remote machine and the local one -share the same directories (through NFS). This is the default. - -This variable becomes local to a buffer when set in any fashion for it. - -It is better to use the function of the same name to change the behavior of -directory tracking in an ssh session once it has begun, rather than -simply setting this variable, since the function does the necessary -re-synching of directories." - :type '(choice (const :tag "off" nil) - (const :tag "ftp" t) - (const :tag "local" local)) - :group 'ssh) - -(make-variable-buffer-local 'ssh-directory-tracking-mode) - -(defcustom ssh-host nil - "*The name of the remote host. This variable is buffer-local." - :type '(choice (const nil) string) - :group 'ssh) - -(defcustom ssh-remote-user nil - "*The username used on the remote host. -This variable is buffer-local and defaults to your local user name. -If ssh is invoked with the `-l' option to specify the remote username, -this variable is set from that." - :type '(choice (const nil) string) - :group 'ssh) - -;; Initialize ssh mode map. -(defvar ssh-mode-map '()) -(cond - ((null ssh-mode-map) - (setq ssh-mode-map (if (consp shell-mode-map) - (cons 'keymap shell-mode-map) - (copy-keymap shell-mode-map))) - (define-key ssh-mode-map "\C-c\C-c" 'ssh-send-Ctrl-C) - (define-key ssh-mode-map "\C-c\C-d" 'ssh-send-Ctrl-D) - (define-key ssh-mode-map "\C-c\C-z" 'ssh-send-Ctrl-Z) - (define-key ssh-mode-map "\C-c\C-\\" 'ssh-send-Ctrl-backslash) - (define-key ssh-mode-map "\C-d" 'ssh-delchar-or-send-Ctrl-D) - (define-key ssh-mode-map "\C-i" 'ssh-tab-or-complete))) - - -;;;###autoload (add-hook 'same-window-regexps "^\\*ssh-.*\\*\\(\\|<[0-9]+>\\)") - -(defvar ssh-history nil) - -;;;###autoload -(defun ssh (input-args &optional buffer) - "Open a network login connection via `ssh' with args INPUT-ARGS. -INPUT-ARGS should start with a host name; it may also contain -other arguments for `ssh'. - -Input is sent line-at-a-time to the remote connection. - -Communication with the remote host is recorded in a buffer `*ssh-HOST*' -\(or `*ssh-USER@HOST*' if the remote username differs\). -If a prefix argument is given and the buffer `*ssh-HOST*' already exists, -a new buffer with a different connection will be made. - -When called from a program, if the optional second argument BUFFER is -a string or buffer, it specifies the buffer to use. - -The variable `ssh-program' contains the name of the actual program to -run. It can be a relative or absolute path. - -The variable `ssh-explicit-args' is a list of arguments to give to -the ssh when starting. They are prepended to any arguments given in -INPUT-ARGS. - -If the default value of `ssh-directory-tracking-mode' is t, then the -default directory in that buffer is set to a remote (FTP) file name to -access your home directory on the remote machine. Occasionally this causes -an error, if you cannot access the home directory on that machine. This -error is harmless as long as you don't try to use that default directory. - -If `ssh-directory-tracking-mode' is neither t nor nil, then the default -directory is initially set up to your (local) home directory. -This is useful if the remote machine and your local machine -share the same files via NFS. This is the default. - -If you wish to change directory tracking styles during a session, use the -function `ssh-directory-tracking-mode' rather than simply setting the -variable." - (interactive (list - (read-from-minibuffer "ssh arguments (hostname first): " - nil nil nil 'ssh-history) - current-prefix-arg)) - - (let* ((process-connection-type ssh-process-connection-type) - (args (ssh-parse-words input-args)) - (host (car args)) - (user (or (car (cdr (member "-l" args))) - (user-login-name))) - (buffer-name (if (string= user (user-login-name)) - (format "*ssh-%s*" host) - (format "*ssh-%s@%s*" user host))) - proc) - - (and ssh-explicit-args - (setq args (append ssh-explicit-args args))) - - (cond ((null buffer)) - ((stringp buffer) - (setq buffer-name buffer)) - ((bufferp buffer) - (setq buffer-name (buffer-name buffer))) - ((numberp buffer) - (setq buffer-name (format "%s<%d>" buffer-name buffer))) - (t - (setq buffer-name (generate-new-buffer-name buffer-name)))) - - (setq buffer (get-buffer-create buffer-name)) - (pop-to-buffer buffer-name) - - (cond - ((comint-check-proc buffer-name)) - (t - (comint-exec buffer buffer-name ssh-program nil args) - (setq proc (get-buffer-process buffer)) - ;; Set process-mark to point-max in case there is text in the - ;; buffer from a previous exited process. - (set-marker (process-mark proc) (point-max)) - - ;; comint-output-filter-functions is just like a hook, except that the - ;; functions in that list are passed arguments. add-hook serves well - ;; enough for modifying it. - ;; comint-output-filter-functions should already have a - ;; permanent-local property, at least in emacs 19.27 or later. - (if (fboundp 'make-local-hook) - (make-local-hook 'comint-output-filter-functions) - (make-local-variable 'comint-output-filter-functions)) - (add-hook 'comint-output-filter-functions 'ssh-carriage-filter) - - (ssh-mode) - - (make-local-variable 'ssh-host) - (setq ssh-host host) - (make-local-variable 'ssh-remote-user) - (setq ssh-remote-user user) - - (condition-case () - (cond ((eq ssh-directory-tracking-mode t) - ;; Do this here, rather than calling the tracking mode - ;; function, to avoid a gratuitous resync check; the default - ;; should be the user's home directory, be it local or remote. - (setq comint-file-name-prefix - (concat "/" ssh-remote-user "@" ssh-host ":")) - (cd-absolute comint-file-name-prefix)) - ((null ssh-directory-tracking-mode)) - (t - (cd-absolute (concat comint-file-name-prefix "~/")))) - (error nil)))))) - -(put 'ssh-mode 'mode-class 'special) - -(defun ssh-mode () - "Set major-mode for ssh sessions. -If `ssh-mode-hook' is set, run it." - (interactive) - (kill-all-local-variables) - (shell-mode) - (setq major-mode 'ssh-mode) - (setq mode-name "ssh") - (use-local-map ssh-mode-map) - (setq shell-dirtrackp ssh-directory-tracking-mode) - (make-local-variable 'comint-file-name-prefix) - (run-hooks 'ssh-mode-hook)) - -(defun ssh-directory-tracking-mode (&optional prefix) - "Do remote or local directory tracking, or disable entirely. - -If called with no prefix argument or a unspecified prefix argument (just -``\\[universal-argument]'' with no number) do remote directory tracking via -ange-ftp. If called as a function, give it no argument. - -If called with a negative prefix argument, disable directory tracking -entirely. - -If called with a positive, numeric prefix argument, e.g. -``\\[universal-argument] 1 M-x ssh-directory-tracking-mode\'', -then do directory tracking but assume the remote filesystem is the same as -the local system. This only works in general if the remote machine and the -local one share the same directories (through NFS)." - (interactive "P") - (cond - ((or (null prefix) - (consp prefix)) - (setq ssh-directory-tracking-mode t) - (setq shell-dirtrackp t) - (setq comint-file-name-prefix - (concat "/" ssh-remote-user "@" ssh-host ":"))) - ((< prefix 0) - (setq ssh-directory-tracking-mode nil) - (setq shell-dirtrackp nil)) - (t - (setq ssh-directory-tracking-mode 'local) - (setq comint-file-name-prefix "") - (setq shell-dirtrackp t))) - (cond - (shell-dirtrackp - (let* ((proc (get-buffer-process (current-buffer))) - (proc-mark (process-mark proc)) - (current-input (buffer-substring proc-mark (point-max))) - (orig-point (point)) - (offset (and (>= orig-point proc-mark) - (- (point-max) orig-point)))) - (unwind-protect - (progn - (delete-region proc-mark (point-max)) - (goto-char (point-max)) - (shell-resync-dirs)) - (goto-char proc-mark) - (insert current-input) - (if offset - (goto-char (- (point-max) offset)) - (goto-char orig-point))))))) - - -;; Parse a line into its constituent parts (words separated by -;; whitespace). Return a list of the words. -(defun ssh-parse-words (line) - (let ((list nil) - (posn 0) - (match-data (match-data))) - (while (string-match "[^ \t\n]+" line posn) - (setq list (cons (substring line (match-beginning 0) (match-end 0)) - list)) - (setq posn (match-end 0))) - (store-match-data (match-data)) - (nreverse list))) - -(defun ssh-carriage-filter (string) - (let* ((point-marker (point-marker)) - (end (process-mark (get-buffer-process (current-buffer)))) - (beg (or (and (boundp 'comint-last-output-start) - comint-last-output-start) - (- end (length string))))) - (goto-char beg) - (while (search-forward "\C-m" end t) - (delete-char -1)) - (goto-char point-marker))) - -(defun ssh-send-Ctrl-C () - (interactive) - (send-string nil "\C-c")) - -(defun ssh-send-Ctrl-D () - (interactive) - (send-string nil "\C-d")) - -(defun ssh-send-Ctrl-Z () - (interactive) - (send-string nil "\C-z")) - -(defun ssh-send-Ctrl-backslash () - (interactive) - (send-string nil "\C-\\")) - -(defun ssh-delchar-or-send-Ctrl-D (arg) - "\ -Delete ARG characters forward, or send a C-d to process if at end of buffer." - (interactive "p") - (if (eobp) - (ssh-send-Ctrl-D) - (delete-char arg))) - -(defun ssh-tab-or-complete () - "Complete file name if doing directory tracking, or just insert TAB." - (interactive) - (if ssh-directory-tracking-mode - (comint-dynamic-complete) - (insert "\C-i"))) - -;;; ssh.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/comint/telnet.el --- a/lisp/comint/telnet.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ -;;; telnet.el --- run a telnet session from within an Emacs buffer - -;;; Copyright (C) 1985, 1988, 1992, 1994 Free Software Foundation, Inc. - -;; Author: William F. Schelter -;; Keywords: comm, unix -;; Maintainer: FSF - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; This mode is intended to be used for telnet or rsh to a remode host; -;; `telnet' and `rsh' are the two entry points. Multiple telnet or rsh -;; sessions are supported. -;; -;; Normally, input is sent to the remote telnet/rsh line-by-line, as you -;; type RET or LFD. C-c C-c sends a C-c to the remote immediately; -;; C-c C-z sends C-z immediately. C-c C-q followed by any character -;; sends that character immediately. -;; -;; All RET characters are filtered out of the output coming back from the -;; remote system. The mode tries to do other useful translations based -;; on what it sees coming back from the other system before the password -;; query. It knows about UNIX, ITS, TOPS-20 and Explorer systems. - -;;; Code: - -;; to do fix software types for lispm: -;; to eval current expression. Also to try to send escape keys correctly. -;; essentially we'll want the rubout-handler off. - -;; filter is simplistic but should be okay for typical shell usage. -;; needs hacking if it is going to deal with asynchronous output in a sane -;; manner - -(require 'comint) - -(defgroup telnet nil - "Run a telnet session from within an Emacs buffer." - :group 'comint) - -(defvar telnet-new-line "\r") -(defvar telnet-mode-map nil) -(defvar telnet-default-prompt-pattern "^[^#$%>\n]*[#$%>] *") -(defvar telnet-prompt-pattern telnet-default-prompt-pattern) - -(defvar telnet-replace-c-g nil) -(make-variable-buffer-local - (defvar telnet-remote-echoes t - "True if the telnet process will echo input.")) -(make-variable-buffer-local - (defvar telnet-interrupt-string "\C-c" "String sent by C-c.")) - -(defvar telnet-count 0 - "Number of output strings read from the telnet process -while looking for the initial password.") -;; (make-variable-buffer-local 'telnet-count) - -(defcustom telnet-program "telnet" - "*Program to run to open a telnet connection." - :type 'string - :group 'telnet) - -(defcustom rsh-eat-password-string nil - "Non-nil means rsh will look for a string matching a password prompt." - :type 'boolean - :group 'telnet) - -(defvar telnet-initial-count -75 - "Initial value of `telnet-count'. Should be set to the negative of the -number of terminal writes telnet will make setting up the host connection.") - -(defvar telnet-maximum-count 4 - "Maximum value `telnet-count' can have. -After this many passes, we stop looking for initial setup data. -Should be set to the number of terminal writes telnet will make -rejecting one login and prompting again for a username and password.") - -(defun telnet-interrupt-subjob () - (interactive) - "Interrupt the program running through telnet on the remote host." - (process-send-string nil telnet-interrupt-string)) - -(defun telnet-c-z () - (interactive) - (process-send-string nil "\C-z")) - -;; XEmacs change (Keep telnet- prefix) -(defun telnet-send-process-next-char () - (interactive) - (process-send-string nil - (char-to-string - (let ((inhibit-quit t)) - (prog1 (read-char) - (setq quit-flag nil)))))) - -; initialization on first load. -(if telnet-mode-map - nil - ;; FSF - ;; (setq telnet-mode-map (nconc (make-sparse-keymap) comint-mode-map)) - (setq telnet-mode-map (make-sparse-keymap)) - (set-keymap-parents telnet-mode-map (list comint-mode-map)) - (define-key telnet-mode-map "\C-m" 'telnet-send-input) -; (define-key telnet-mode-map "\C-j" 'telnet-send-input) - (define-key telnet-mode-map "\C-c\C-q" 'telnet-send-process-next-char) - (define-key telnet-mode-map "\C-c\C-c" 'telnet-interrupt-subjob) - (define-key telnet-mode-map "\C-c\C-z" 'telnet-c-z)) - -;;maybe should have a flag for when have found type -(defun telnet-check-software-type-initialize (string) - "Tries to put correct initializations in. Needs work." - (let ((case-fold-search t)) - (cond ((string-match "unix" string) - (setq telnet-prompt-pattern shell-prompt-pattern) - (setq telnet-new-line "\n")) - ((string-match "tops-20" string) ;;maybe add telnet-replace-c-g - (setq telnet-prompt-pattern "[@>] *")) - ((string-match "its" string) - (setq telnet-prompt-pattern "^[^*>\n]*[*>] *")) - ((string-match "explorer" string) ;;explorer telnet needs work - (setq telnet-replace-c-g ?\n)))) - (setq comint-prompt-regexp telnet-prompt-pattern)) - -(defun telnet-initial-filter (proc string) - (let ((case-fold-search t)) - ;For reading up to and including password; also will get machine type. - (cond ((string-match "No such host" string) - (kill-buffer (process-buffer proc)) - (error "No such host.")) - ((string-match "passw" string) - (telnet-filter proc string) - (let ((password (comint-read-noecho "Password: " t))) - (setq telnet-count 0) - (process-send-string proc (concat password telnet-new-line)))) - (t (telnet-check-software-type-initialize string) - (telnet-filter proc string) - (cond ((> telnet-count telnet-maximum-count) - ;; (set-process-filter proc 'telnet-filter) Kludge - ;; for shell-fonts -- this is the only mode that - ;; actually changes what its process filter is at - ;; run time, which confuses shell-font. So we - ;; special-case that here. - ;; #### Danger, knows an internal shell-font variable name. - (let ((old-filter (process-filter proc))) - (if (eq old-filter 'shell-font-process-filter) - (set (make-local-variable 'shell-font-process-filter) - 'telnet-filter) - (set-process-filter proc 'telnet-filter)))) - (t (setq telnet-count (1+ telnet-count)))))))) - -;; Identical to comint-simple-send, except that it sends telnet-new-line -;; instead of "\n". -(defun telnet-simple-send (proc string) - (comint-send-string proc string) - (comint-send-string proc telnet-new-line)) - -(defun telnet-filter (proc string) - (save-excursion - (set-buffer (process-buffer proc)) - (save-match-data - (let* ((last-insertion (marker-position (process-mark proc))) - (delta (- (point) last-insertion)) - (ie (and comint-last-input-end - (marker-position comint-last-input-end))) - (w (get-buffer-window (current-buffer))) - (ws (and w (window-start w)))) - (goto-char last-insertion) - ;; Insert STRING, omitting all C-m characters. - (insert-before-markers string) - (set-marker (process-mark proc) (point)) - ;; the insert-before-markers may have screwed window-start - ;; and likely moved comint-last-input-end. This is why the - ;; insertion-reaction should be a property of markers, not - ;; of the function which does the inserting. - (if ws (set-window-start w ws t)) - (if ie (set-marker comint-last-input-end ie)) - (while (progn (skip-chars-backward "^\C-m" last-insertion) - (> (point) last-insertion)) - (delete-region (1- (point)) (point))) - (goto-char (process-mark proc)) - (and telnet-replace-c-g - (subst-char-in-region last-insertion (point) ?\C-g - telnet-replace-c-g t)) - ;; If point is after the insertion place, move it - ;; along with the text. - (if (> delta 0) - (goto-char (+ (process-mark proc) delta))))))) - -(defun telnet-send-input () - (interactive) - (let ((proc (get-buffer-process (current-buffer))) - p1 p2) - (if (and telnet-remote-echoes - (>= (point) (process-mark proc))) - (save-excursion - (if comint-eol-on-send (end-of-line)) - (setq p1 (marker-position (process-mark proc)) - p2 (point)))) - (prog1 - (comint-send-input) - ;; at this point, comint-send-input has moved the process mark, inserted - ;; a newline, and possibly inserted the (echoed) output. If the host is - ;; in remote-echo mode, then delete our local copy of the command, and - ;; the newline that comint-send-input sent. - (if p1 - (delete-region p1 (1+ p2)))))) - -;;;###autoload (add-hook 'same-window-regexps "\\*telnet-.*\\*\\(\\|<[0-9]+>\\)") - -;;;###autoload -(defun telnet (host &optional port) - "Open a network login connection to host named HOST (a string). -With a prefix argument, prompts for the port name or number as well. -Communication with HOST is recorded in a buffer `*HOST-telnet*'. -Normally input is edited in Emacs and sent a line at a time. -See also `\\[rsh]'." - (interactive (list (read-string "Open telnet connection to host: ") - (if current-prefix-arg - (read-string "Port name or number: ") - nil))) - (let* ((comint-delimiter-argument-list '(?\ ?\t)) - (name (concat "telnet-" (comint-arguments host 0 nil) - (if port (concat "/" port) ""))) - (buffer (get-buffer (concat "*" name "*"))) - process) - (if (and buffer (get-buffer-process buffer)) - (pop-to-buffer buffer) - (pop-to-buffer (make-comint name telnet-program)) - (setq process (get-buffer-process (current-buffer))) - (set-process-filter process 'telnet-initial-filter) - - ;; SunOS and IRIX don't print "unix" in their rsh or telnet - ;; login banners, so let's get a reasonable default here. - ;; #### This patch from jwz mimics what is done in rsh done - ;; below. However, it (along with the one in rsh) mean that - ;; telnet-check-software-type-initialize is effectively a - ;; wastoid function. Reworking it like it claims to need is - ;; probably the better solution but I'm not going to do it. - ;; --cet - (telnet-check-software-type-initialize "unix") - - ;; Don't send the `open' cmd till telnet is ready for it. - (accept-process-output process) - (erase-buffer) - (process-send-string process (concat "open " host - (if port (concat " " port) "") - "\n")) - (setq comint-input-sender 'telnet-simple-send) - ;; run last so that hooks can change things. - (telnet-mode)))) - -(defun telnet-mode () - "This mode is for using telnet (or rsh) from a buffer to another host. -It has most of the same commands as comint-mode. -There is a variable ``telnet-interrupt-string'' which is the character -sent to try to stop execution of a job on the remote host. -Data is sent to the remote host when RET is typed. - -\\{telnet-mode-map} -" - (interactive) - (comint-mode) - (setq major-mode 'telnet-mode - mode-name "Telnet" - comint-prompt-regexp telnet-prompt-pattern) - (use-local-map telnet-mode-map) - (set (make-local-variable 'telnet-count) telnet-initial-count) - (run-hooks 'telnet-mode-hook)) - -;;;###autoload (add-hook 'same-window-regexps "\\*rsh-[^-]*\\*\\(\\|<[0-9]*>\\)") - -;; Berkeley spawn of hell -;;;###autoload -(defun rsh (host) - "Open a network login connection to host named HOST (a string). -Communication with HOST is recorded in a buffer `*rsh-HOST*'. -Normally input is edited in Emacs and sent a line at a time. -See also `\\[telnet]'." - (interactive "sOpen rsh connection to host: ") - (require 'shell) - (let ((name (concat "rsh-" host))) - (pop-to-buffer (make-comint name remote-shell-program nil host)) - (setq telnet-count telnet-initial-count) - ;; - ;; SunOS doesn't print "unix" in its rsh login banner, so let's get a - ;; reasonable default here. There do exist non-Unix machines which - ;; speak the rsh protocol, but let's hope they print their OS name - ;; when one connects. - ;; - (telnet-check-software-type-initialize "unix") - ;; - ;; I think we should use telnet-filter here instead of -initial-filter, - ;; because rsh generally doesn't prompt for a password, and gobbling the - ;; first line that contains "passw" is extremely antisocial. More - ;; antisocial than echoing a password, and more likely than connecting - ;; to a non-Unix rsh host these days... - ;; - ;; I disagree with the above. -sb - ;; - (set-process-filter (get-process name) (if rsh-eat-password-string - 'telnet-initial-filter - 'telnet-filter)) - ;; (set-process-filter (get-process name) 'telnet-filter) - ;; run last so that hooks can change things. - (telnet-mode))) - -(provide 'telnet) - -;;; telnet.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/console.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/console.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,49 @@ +;;; console.el --- miscellaneous console functions not written in C + +;; Copyright (C) 1994-5, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995, 1996 Ben Wing + +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +(defun quit-char (&optional console) + "Return the character that causes a QUIT to happen. +This is normally C-g. Optional arg CONSOLE specifies the console +that the information is returned for; nil means the current console." + (nth 3 (current-input-mode console))) + +(defun resume-pid-console (pid) + "Resume the consoles with a controlling process of PID." + (mapc (lambda (c) + (if (and (eq (console-type c) 'tty) + (eql pid (console-tty-controlling-process c))) + (resume-console c))) + (console-list)) + nil) + +;;; console.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cus-dep.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cus-dep.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,182 @@ +;;; cus-dep.el --- Find customization dependencies. +;; +;; Copyright (C) 1997 Free Software Foundation, Inc. +;; +;; Author: Per Abrahamsen , then +;; Richar Stallman , then +;; Hrvoje Niksic (rewritten for XEmacs) +;; Maintainer: Hrvoje Niksic +;; Keywords: internal + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not synched with FSF. + + +;;; Commentary: + +;; This file generates the custom-load files, loaded by cus-load.el. +;; The only entry point is `Custom-make-dependencies'. + +;; It works by scanning all the `.el' files in a directory, and +;; evaluates any `defcustom', `defgroup', or `defface' expression that +;; it finds. The symbol changed by this expression is stored to a +;; hash table as the hash key, file name being the value. + +;; After all the files have been examined, custom-loads.el is +;; generated by mapping all the atoms, and seeing if any of them +;; contains a `custom-group' property. This property is a list whose +;; each element's car is the "child" group symbol. If that property +;; is in the hash-table, the file name will be looked up from the +;; hash-table, and added to cusload-file. Because the hash-table is +;; cleared whenever we process a new directory, we cannot get confused +;; by custom-loads from another directory, or from a previous +;; installation. This is also why it is perfectly safe to have old +;; custom-loads around, and have them loaded by `cus-load.el' (as +;; invoked by `cus-edit.el'). + +;; A trivial, but useful optimization is that if cusload-file exists, +;; and no .el files in the directory are newer than cusload-file, it +;; will not be generated. This means that the directories where +;; nothing has changed will be skipped. + +;; The `custom-put' function, used by files generated by +;; `Custom-make-dependencies', is a specialized function that updates +;; a property (which must be a list of strings) with a new list of +;; strings, eliminating the duplicates. As it also adds an +;; appropriate entry to a custom hash-table, *do not* use it outside +;; of custom. Its inner workings can change anytime, without prior +;; notice. `custom-put' is defined in `cus-load.el'. + +;; Example: + +;; (custom-put 'foo 'custom-loads '("bar" "baz")) +;; (get 'foo 'custom-loads) +;; => ("bar" "baz") +;; +;; (custom-put 'foo 'custom-loads '("hmph" "baz" "quz")) +;; (get 'foo 'custom-loads) +;; => ("bar" "baz" "hmph" "qux") + +;; Obviously, this allows correct incremental loading of custom-load +;; files. This is not necessary under FSF (they use a simple `put'), +;; since they have only *one* file. With the advent of packages, we +;; cannot afford the same luxury. + + +;;; Code: + +(require 'cl) +(require 'widget) +(require 'cus-face) + +;; Don't change this, unless you plan to change the code in +;; cus-start.el, too. +(defconst cusload-base-file "custom-load.el") + +;; Be very careful when changing this function. It looks easy to +;; understand, but is in fact very easy to break. Be sure to read and +;; understand the commentary above! + +;;;###autoload +(defun Custom-make-dependencies (&optional subdirs) + "Extract custom dependencies from .el files in SUBDIRS. +SUBDIRS is a list of directories. If it is nil, the command-line +arguments are used. If it is a string, only that directory is +processed. This function is especially useful in batch mode. + +Batch usage: xemacs -batch -l cus-dep.el -f Custom-make-dependencies DIRS" + (interactive "DDirectory: ") + (and (stringp subdirs) + (setq subdirs (list subdirs))) + (or subdirs + ;; Usurp the command-line-args + (setq subdirs command-line-args-left + command-line-args-left nil)) + (setq subdirs (mapcar #'expand-file-name subdirs)) + (with-temp-buffer + (let ((enable-local-eval nil) + (hash (make-hash-table :test 'eq))) + (dolist (dir subdirs) + (princ (format "Processing %s\n" dir)) + (let ((cusload-file (expand-file-name cusload-base-file dir)) + (files (directory-files dir t "\\`[^=].*\\.el\\'"))) + ;; A trivial optimization: if no file in the directory is + ;; newer than custom-load.el, no need to do anything! + (if (and (file-exists-p cusload-file) + (dolist (file files t) + (when (file-newer-than-file-p file cusload-file) + (return nil)))) + (princ "(No changes need to be written)\n") + ;; Process directory + (dolist (file files) + (when (file-exists-p file) + (erase-buffer) + (insert-file-contents file) + (goto-char (point-min)) + (let ((name (file-name-sans-extension + (file-name-nondirectory file)))) + ;; Search for defcustom/defface/defgroup + ;; expressions, and evaluate them. + (ignore-errors + (while (re-search-forward + "^(defcustom\\|^(defface\\|^(defgroup" + nil t) + (beginning-of-line) + (let ((expr (read (current-buffer)))) + (eval expr) + ;; Hash the file of the affected symbol. + (setf (gethash (nth 1 expr) hash) name))))))) + (cond + ((zerop (hash-table-count hash)) + (princ "(No customization dependencies") + (when (file-exists-p cusload-file) + (princ (format ", deleting %s" cusload-file)) + (delete-file cusload-file)) + (princ ")\n")) + (t + (princ (format "Generating %s...\n" cusload-base-file)) + (with-temp-file cusload-file + (insert ";;; " cusload-base-file + " --- automatically extracted custom dependencies\n" + "\n\n;;; Code:\n\n") + (mapatoms + (lambda (sym) + (let ((members (get sym 'custom-group)) + item where found) + (when members + (while members + (setq item (car (car members)) + members (cdr members) + where (gethash item hash)) + (unless (or (null where) + (member where found)) + (if found + (insert " ") + (insert "(custom-add-loads '" + (symbol-name sym) " '(")) + (prin1 where (current-buffer)) + (push where found))) + (when found + (insert "))\n")))))) + (insert "\n;;; custom-load.el ends here\n")) + (clrhash hash))))))))) + +(provide 'cus-dep) + +;;; cus-dep.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cus-edit.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cus-edit.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,3234 @@ +;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages. +;; +;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. +;; +;; Author: Per Abrahamsen +;; Maintainer: Hrvoje Niksic +;; Keywords: help, faces +;; Version: 1.9960-x +;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; +;; This file implements the code to create and edit customize buffers. +;; +;; See `custom.el'. + +;; No commands should have names starting with `custom-' because +;; that interferes with completion. Use `customize-' for commands +;; that the user will run with M-x, and `Custom-' for interactive commands. + + +;;; Code: + +(require 'cus-face) +(require 'wid-edit) +(require 'easymenu) + +(require 'cus-load) +(require 'cus-start) + +;; Huh? This looks dirty! +(put 'custom-define-hook 'custom-type 'hook) +(put 'custom-define-hook 'standard-value '(nil)) +(custom-add-to-group 'customize 'custom-define-hook 'custom-variable) + +;;; Customization Groups. + +(defgroup emacs nil + "Customization of the One True Editor." + :link '(custom-manual "(XEmacs)Top")) + +;; Most of these groups are stolen from `finder.el', +(defgroup editing nil + "Basic text editing facilities." + :group 'emacs) + +(defgroup abbrev nil + "Abbreviation handling, typing shortcuts, macros." + :tag "Abbreviations" + :group 'editing) + +(defgroup matching nil + "Various sorts of searching and matching." + :group 'editing) + +(defgroup emulations nil + "Emulations of other editors." + :group 'editing) + +(defgroup mouse nil + "Mouse support." + :group 'editing) + +(defgroup outlines nil + "Support for hierarchical outlining." + :group 'editing) + +(defgroup external nil + "Interfacing to external utilities." + :group 'emacs) + +(defgroup bib nil + "Code related to the `bib' bibliography processor." + :tag "Bibliography" + :group 'external) + +(defgroup processes nil + "Process, subshell, compilation, and job control support." + :group 'external + :group 'development) + +(defgroup programming nil + "Support for programming in other languages." + :group 'emacs) + +(defgroup languages nil + "Specialized modes for editing programming languages." + :group 'programming) + +(defgroup lisp nil + "Lisp support, including Emacs Lisp." + :group 'languages + :group 'development) + +(defgroup c nil + "Support for the C language and related languages." + :group 'languages) + +(defgroup tools nil + "Programming tools." + :group 'programming) + +(defgroup oop nil + "Support for object-oriented programming." + :group 'programming) + +(defgroup applications nil + "Applications written in Emacs." + :group 'emacs) + +(defgroup calendar nil + "Calendar and time management support." + :group 'applications) + +(defgroup mail nil + "Modes for electronic-mail handling." + :group 'applications) + +(defgroup news nil + "Support for netnews reading and posting." + :group 'applications) + +(defgroup games nil + "Games, jokes and amusements." + :group 'applications) + +(defgroup development nil + "Support for further development of Emacs." + :group 'emacs) + +(defgroup docs nil + "Support for Emacs documentation." + :group 'development) + +(defgroup extensions nil + "Emacs Lisp language extensions." + :group 'development) + +(defgroup internal nil + "Code for Emacs internals, build process, defaults." + :group 'development) + +(defgroup maint nil + "Maintenance aids for the Emacs development group." + :tag "Maintenance" + :group 'development) + +(defgroup environment nil + "Fitting Emacs with its environment." + :group 'emacs) + +(defgroup comm nil + "Communications, networking, remote access to files." + :tag "Communication" + :group 'environment) + +(defgroup hardware nil + "Support for interfacing with exotic hardware." + :group 'environment) + +(defgroup terminals nil + "Support for terminal types." + :group 'environment) + +(defgroup unix nil + "Front-ends/assistants for, or emulators of, UNIX features." + :group 'environment) + +(defgroup vms nil + "Support code for vms." + :group 'environment) + +(defgroup i18n nil + "Internationalization and alternate character-set support." + :group 'environment + :group 'editing) + +(defgroup x nil + "The X Window system." + :group 'environment) + +(defgroup frames nil + "Support for Emacs frames and window systems." + :group 'environment) + +(defgroup data nil + "Support editing files of data." + :group 'emacs) + +(defgroup files nil + "Support editing files." + :group 'emacs) + +(defgroup wp nil + "Word processing." + :group 'emacs) + +(defgroup tex nil + "Code related to the TeX formatter." + :group 'wp) + +(defgroup faces nil + "Support for multiple fonts." + :group 'emacs) + +(defgroup hypermedia nil + "Support for links between text or other media types." + :group 'emacs) + +(defgroup help nil + "Support for on-line help systems." + :group 'emacs) + +(defgroup local nil + "Code local to your site." + :group 'emacs) + +(defgroup customize '((widgets custom-group)) + "Customization of the Customization support." + :link '(custom-manual "(custom)Top") + :link '(url-link :tag "Development Page" + "http://www.dina.kvl.dk/~abraham/custom/") + :prefix "custom-" + :group 'help) + +(defgroup custom-faces nil + "Faces used by customize." + :group 'customize + :group 'faces) + +(defgroup custom-browse nil + "Control customize browser." + :prefix "custom-" + :group 'customize) + +(defgroup custom-buffer nil + "Control customize buffers." + :prefix "custom-" + :group 'customize) + +(defgroup custom-menu nil + "Control customize menus." + :prefix "custom-" + :group 'customize) + +(defgroup abbrev-mode nil + "Word abbreviations mode." + :group 'abbrev) + +(defgroup alloc nil + "Storage allocation and gc for GNU Emacs Lisp interpreter." + :tag "Storage Allocation" + :group 'internal) + +(defgroup undo nil + "Undoing changes in buffers." + :group 'editing) + +(defgroup modeline nil + "Content of the modeline." + :group 'environment) + +(defgroup fill nil + "Indenting and filling text." + :group 'editing) + +(defgroup editing-basics nil + "Most basic editing facilities." + :group 'editing) + +(defgroup display nil + "How characters are displayed in buffers." + :group 'environment) + +(defgroup execute nil + "Executing external commands." + :group 'processes) + +(defgroup installation nil + "The Emacs installation." + :group 'environment) + +(defgroup dired nil + "Directory editing." + :group 'environment) + +(defgroup limits nil + "Internal Emacs limits." + :group 'internal) + +(defgroup debug nil + "Debugging Emacs itself." + :group 'development) + +(defgroup minibuffer nil + "Controling the behaviour of the minibuffer." + :group 'environment) + +(defgroup keyboard nil + "Input from the keyboard." + :group 'environment) + +(defgroup mouse nil + "Input from the mouse." + :group 'environment) + +(defgroup menu nil + "Input from the menus." + :group 'environment) + +(defgroup auto-save nil + "Preventing accidential loss of data." + :group 'files) + +(defgroup processes-basics nil + "Basic stuff dealing with processes." + :group 'processes) + +(defgroup mule nil + "MULE Emacs internationalization." + :group 'i18n) + +(defgroup windows nil + "Windows within a frame." + :group 'environment) + + +;;; Utilities. + +(defun custom-quote (sexp) + "Quote SEXP iff it is not self quoting." + (if (or (memq sexp '(t nil)) + (keywordp sexp) + (eq (car-safe sexp) 'lambda) + (stringp sexp) + (numberp sexp) + (characterp sexp)) + sexp + (list 'quote sexp))) + +(defun custom-split-regexp-maybe (regexp) + "If REGEXP is a string, split it to a list at `\\|'. +You can get the original back with from the result with: + (mapconcat 'identity result \"\\|\") + +IF REGEXP is not a string, return it unchanged." + (if (stringp regexp) + (split-string regexp "\\\\|") + regexp)) + +(defun custom-variable-prompt () + ;; Code stolen from `help.el'. + "Prompt for a variable, defaulting to the variable at point. +Return a list suitable for use in `interactive'." + (let ((v (variable-at-point)) + (enable-recursive-minibuffers t) + val) + (setq val (completing-read + (if (symbolp v) + (format "Customize variable: (default %s) " v) + "Customize variable: ") + obarray (lambda (symbol) + (and (boundp symbol) + (or (get symbol 'custom-type) + (user-variable-p symbol)))))) + (list (if (equal val "") + (if (symbolp v) v nil) + (intern val))))) + +;; Here we take not only the actual groups, but the loads, too. +(defun custom-group-prompt (prompt) + "Read group from minibuffer." + (let ((completion-ignore-case t)) + (list (completing-read + prompt obarray + (lambda (symbol) + (or (get symbol 'custom-group) + (get symbol 'custom-loads))) + t)))) + +(defun custom-menu-filter (menu widget) + "Convert MENU to the form used by `widget-choose'. +MENU should be in the same format as `custom-variable-menu'. +WIDGET is the widget to apply the filter entries of MENU on." + (let ((result nil) + current name action filter) + (while menu + (setq current (car menu) + name (nth 0 current) + action (nth 1 current) + filter (nth 2 current) + menu (cdr menu)) + (if (or (null filter) (funcall filter widget)) + (push (cons name action) result) + (push name result))) + (nreverse result))) + + +;;; Unlispify. + +(defvar custom-prefix-list nil + "List of prefixes that should be ignored by `custom-unlispify'") + +(defcustom custom-unlispify-menu-entries t + "Display menu entries as words instead of symbols if non nil." + :group 'custom-menu + :type 'boolean) + +(defcustom custom-unlispify-remove-prefixes t + "Non-nil means remove group prefixes from option names in buffers and menus." + :group 'custom-menu + :type 'boolean) + +(defun custom-unlispify-menu-entry (symbol &optional no-suffix) + "Convert symbol into a menu entry." + (cond ((not custom-unlispify-menu-entries) + (symbol-name symbol)) + ((get symbol 'custom-tag) + (if no-suffix + (get symbol 'custom-tag) + (concat (get symbol 'custom-tag) "..."))) + (t + (with-current-buffer (get-buffer-create " *Custom-Work*") + (erase-buffer) + (princ symbol (current-buffer)) + (goto-char (point-min)) + (when (and (eq (get symbol 'custom-type) 'boolean) + (re-search-forward "-p\\'" nil t)) + (replace-match "" t t) + (goto-char (point-min))) + (when custom-unlispify-remove-prefixes + (let ((prefixes custom-prefix-list) + prefix) + (while prefixes + (setq prefix (car prefixes)) + (if (search-forward prefix (+ (point) (length prefix)) t) + (progn + (setq prefixes nil) + (delete-region (point-min) (point))) + (setq prefixes (cdr prefixes)))))) + (subst-char-in-region (point-min) (point-max) ?- ?\ t) + (capitalize-region (point-min) (point-max)) + (unless no-suffix + (goto-char (point-max)) + (insert "...")) + (buffer-string))))) + +(defcustom custom-unlispify-tag-names t + "Display tag names as words instead of symbols if non nil." + :group 'custom-buffer + :type 'boolean) + +(defun custom-unlispify-tag-name (symbol) + "Convert symbol into a menu entry." + (let ((custom-unlispify-menu-entries custom-unlispify-tag-names)) + (custom-unlispify-menu-entry symbol t))) + +(defun custom-prefix-add (symbol prefixes) + ;; Addd SYMBOL to list of ignored PREFIXES. + (cons (or (get symbol 'custom-prefix) + (concat (symbol-name symbol) "-")) + prefixes)) + + +;;; Guess. + +(defcustom custom-guess-name-alist + '(("-p\\'" boolean) + ("-hooks?\\'" hook) + ("-face\\'" face) + ("-file\\'" file) + ("-function\\'" function) + ("-functions\\'" (repeat function)) + ("-list\\'" (repeat sexp)) + ("-alist\\'" (repeat (cons sexp sexp)))) + "Alist of (MATCH TYPE). + +MATCH should be a regexp matching the name of a symbol, and TYPE should +be a widget suitable for editing the value of that symbol. The TYPE +of the first entry where MATCH matches the name of the symbol will be +used. + +This is used for guessing the type of variables not declared with +customize." + :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type"))) + :group 'customize) + +(defcustom custom-guess-doc-alist + '(("\\`\\*?Non-nil " boolean)) + "Alist of (MATCH TYPE). + +MATCH should be a regexp matching a documentation string, and TYPE +should be a widget suitable for editing the value of a variable with +that documentation string. The TYPE of the first entry where MATCH +matches the name of the symbol will be used. + +This is used for guessing the type of variables not declared with +customize." + :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type"))) + :group 'customize) + +(defun custom-guess-type (symbol) + "Guess a widget suitable for editing the value of SYMBOL. +This is done by matching SYMBOL with `custom-guess-name-alist' and +if that fails, the doc string with `custom-guess-doc-alist'." + (let ((name (symbol-name symbol)) + (names custom-guess-name-alist) + current found) + (while names + (setq current (car names) + names (cdr names)) + (when (string-match (nth 0 current) name) + (setq found (nth 1 current) + names nil))) + (unless found + (let ((doc (documentation-property symbol 'variable-documentation)) + (docs custom-guess-doc-alist)) + (when doc + (while docs + (setq current (car docs) + docs (cdr docs)) + (when (string-match (nth 0 current) doc) + (setq found (nth 1 current) + docs nil)))))) + found)) + + +;;; Sorting. + +(defcustom custom-browse-sort-alphabetically nil + "If non-nil, sort members of each customization group alphabetically." + :type 'boolean + :group 'custom-browse) + +(defcustom custom-browse-order-groups nil + "If non-nil, order group members within each customization group. +If `first', order groups before non-groups. +If `last', order groups after non-groups." + :type '(choice (const first) + (const last) + (const :tag "none" nil)) + :group 'custom-browse) + +(defcustom custom-browse-only-groups nil + "If non-nil, show group members only within each customization group." + :type 'boolean + :group 'custom-browse) + +(defcustom custom-buffer-sort-alphabetically nil + "If non-nil, sort members of each customization group alphabetically." + :type 'boolean + :group 'custom-buffer) + +(defcustom custom-buffer-order-groups 'last + "If non-nil, order group members within each customization group. +If `first', order groups before non-groups. +If `last', order groups after non-groups." + :type '(choice (const first) + (const last) + (const :tag "none" nil)) + :group 'custom-buffer) + +(defcustom custom-menu-sort-alphabetically nil + "If non-nil, sort members of each customization group alphabetically." + :type 'boolean + :group 'custom-menu) + +(defcustom custom-menu-order-groups 'first + "If non-nil, order group members within each customization group. +If `first', order groups before non-groups. +If `last', order groups after non-groups." + :type '(choice (const first) + (const last) + (const :tag "none" nil)) + :group 'custom-menu) + +(defun custom-sort-items (items sort-alphabetically order-groups) + "Return a sorted copy of ITEMS. +ITEMS should be a `custom-group' property. +If SORT-ALPHABETICALLY non-nil, sort alphabetically. +If ORDER-GROUPS is `first' order groups before non-groups, if `last' order +groups after non-groups, if nil do not order groups at all." + (sort (copy-sequence items) + (lambda (a b) + (let ((typea (nth 1 a)) (typeb (nth 1 b)) + (namea (symbol-name (nth 0 a))) (nameb (symbol-name (nth 0 b)))) + (cond ((not order-groups) + ;; Since we don't care about A and B order, maybe sort. + (when sort-alphabetically + (string-lessp namea nameb))) + ((eq typea 'custom-group) + ;; If B is also a group, maybe sort. Otherwise, order A and B. + (if (eq typeb 'custom-group) + (when sort-alphabetically + (string-lessp namea nameb)) + (eq order-groups 'first))) + ((eq typeb 'custom-group) + ;; Since A cannot be a group, order A and B. + (eq order-groups 'last)) + (sort-alphabetically + ;; Since A and B cannot be groups, sort. + (string-lessp namea nameb))))))) + + +;;; Custom Mode Commands. + +(defvar custom-options nil + "Customization widgets in the current buffer.") + +(defun Custom-set () + "Set changes in all modified options." + (interactive) + (let ((children custom-options)) + (mapc (lambda (child) + (when (eq (widget-get child :custom-state) 'modified) + (widget-apply child :custom-set))) + children))) + +(defun Custom-save () + "Set all modified group members and save them." + (interactive) + (let ((children custom-options)) + (mapc (lambda (child) + (when (memq (widget-get child :custom-state) '(modified set)) + (widget-apply child :custom-save))) + children)) + (custom-save-all)) + +(defvar custom-reset-menu + '(("Current" . Custom-reset-current) + ("Saved" . Custom-reset-saved) + ("Standard Settings" . Custom-reset-standard)) + "Alist of actions for the `Reset' button. +The key is a string containing the name of the action, the value is a +lisp function taking the widget as an element which will be called +when the action is chosen.") + +(defun custom-reset (event) + "Select item from reset menu." + (let* ((completion-ignore-case t) + (answer (widget-choose "Reset to" + custom-reset-menu + event))) + (if answer + (funcall answer)))) + +(defun Custom-reset-current (&rest ignore) + "Reset all modified group members to their current value." + (interactive) + (let ((children custom-options)) + (mapc (lambda (child) + (when (eq (widget-get child :custom-state) 'modified) + (widget-apply child :custom-reset-current))) + children))) + +(defun Custom-reset-saved (&rest ignore) + "Reset all modified or set group members to their saved value." + (interactive) + (let ((children custom-options)) + (mapc (lambda (child) + (when (eq (widget-get child :custom-state) 'modified) + (widget-apply child :custom-reset-saved))) + children))) + +(defun Custom-reset-standard (&rest ignore) + "Reset all modified, set, or saved group members to their standard settings." + (interactive) + (let ((children custom-options)) + (mapc (lambda (child) + (when (eq (widget-get child :custom-state) 'modified) + (widget-apply child :custom-reset-standard))) + children))) + + +;;; The Customize Commands + +(defun custom-prompt-variable (prompt-var prompt-val) + "Prompt for a variable and a value and return them as a list. +PROMPT-VAR is the prompt for the variable, and PROMPT-VAL is the +prompt for the value. The %s escape in PROMPT-VAL is replaced with +the name of the variable. + +If the variable has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If the variable has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value." + (let* ((var (read-variable prompt-var)) + (minibuffer-help-form '(describe-variable var))) + (list var + (let ((prop (get var 'variable-interactive)) + (type (get var 'custom-type)) + (prompt (format prompt-val var))) + (unless (listp type) + (setq type (list type))) + (cond (prop + ;; Use VAR's `variable-interactive' property + ;; as an interactive spec for prompting. + (call-interactively (list 'lambda '(arg) + (list 'interactive prop) + 'arg))) + (type + (widget-prompt-value type + prompt + (if (boundp var) + (symbol-value var)) + (not (boundp var)))) + (t + (eval-minibuffer prompt))))))) + +;;;###autoload +(defun customize-set-value (var val) + "Set VARIABLE to VALUE. VALUE is a Lisp object. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value." + (interactive (custom-prompt-variable "Set variable: " + "Set %s to value: ")) + + (set var val)) + +;;;###autoload +(defun customize-set-variable (var val) + "Set the default for VARIABLE to VALUE. VALUE is a Lisp object. + +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +The `customized-value' property of the VARIABLE will be set to a list +with a quoted VALUE as its sole list member. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. " + (interactive (custom-prompt-variable "Set variable: " + "Set customized value for %s to: ")) + (funcall (or (get var 'custom-set) 'set-default) var val) + (put var 'customized-value (list (custom-quote val)))) + +;;;###autoload +(defun customize-save-variable (var val) + "Set the default for VARIABLE to VALUE, and save it for future sessions. +If VARIABLE has a `custom-set' property, that is used for setting +VARIABLE, otherwise `set-default' is used. + +The `customized-value' property of the VARIABLE will be set to a list +with a quoted VALUE as its sole list member. + +If VARIABLE has a `variable-interactive' property, that is used as if +it were the arg to `interactive' (which see) to interactively read the value. + +If VARIABLE has a `custom-type' property, it must be a widget and the +`:prompt-value' property of that widget will be used for reading the value. " + (interactive (custom-prompt-variable "Set and ave variable: " + "Set and save value for %s as: ")) + (funcall (or (get var 'custom-set) 'set-default) var val) + (put var 'saved-value (list (custom-quote val))) + (custom-save-all)) + +;;;###autoload +(defun customize (group) + "Select a customization buffer which you can use to set user options. +User options are structured into \"groups\". +The default group is `Emacs'." + (interactive (custom-group-prompt + "Customize group: (default emacs) ")) + (when (stringp group) + (if (string-equal "" group) + (setq group 'emacs) + (setq group (intern group)))) + (let ((name (format "*Customize Group: %s*" + (custom-unlispify-tag-name group)))) + (if (get-buffer name) + (switch-to-buffer name) + (custom-buffer-create (list (list group 'custom-group)) + name + (concat " for group " + (custom-unlispify-tag-name group)))))) + +;;;###autoload +(defalias 'customize-group 'customize) + +;;;###autoload +(defun customize-other-window (symbol) + "Customize SYMBOL, which must be a customization group." + (interactive (custom-group-prompt + "Customize group: (default emacs) ")) + (when (stringp symbol) + (if (string-equal "" symbol) + (setq symbol 'emacs) + (setq symbol (intern symbol)))) + (custom-buffer-create-other-window + (list (list symbol 'custom-group)) + (format "*Customize Group: %s*" (custom-unlispify-tag-name symbol)))) + +;;;###autoload +(defalias 'customize-group-other-window 'customize-other-window) + +;;;###autoload +(defalias 'customize-option 'customize-variable) + +;;;###autoload +(defun customize-variable (symbol) + "Customize SYMBOL, which must be a user option variable." + (interactive (custom-variable-prompt)) + (custom-buffer-create (list (list symbol 'custom-variable)) + (format "*Customize Variable: %s*" + (custom-unlispify-tag-name symbol)))) + +;;;###autoload +(defalias 'customize-variable-other-window 'customize-option-other-window) + +;;;###autoload +(defun customize-option-other-window (symbol) + "Customize SYMBOL, which must be a user option variable. +Show the buffer in another window, but don't select it." + (interactive (custom-variable-prompt)) + (custom-buffer-create-other-window + (list (list symbol 'custom-variable)) + (format "*Customize Option: %s*" (custom-unlispify-tag-name symbol)))) + +;;;###autoload +(defun customize-face (&optional symbol) + "Customize SYMBOL, which should be a face name or nil. +If SYMBOL is nil, customize all faces." + (interactive (list (completing-read "Customize face: (default all) " + obarray 'find-face))) + (if (or (null symbol) (and (stringp symbol) (zerop (length symbol)))) + (custom-buffer-create (custom-sort-items + (mapcar (lambda (symbol) + (list symbol 'custom-face)) + (face-list)) + t nil) + "*Customize Faces*") + (when (stringp symbol) + (setq symbol (intern symbol))) + (unless (symbolp symbol) + (error "Should be a symbol %S" symbol)) + (custom-buffer-create (list (list symbol 'custom-face)) + (format "*Customize Face: %s*" + (custom-unlispify-tag-name symbol))))) + +;;;###autoload +(defun customize-face-other-window (&optional symbol) + "Show customization buffer for FACE in other window." + (interactive (list (completing-read "Customize face: " + obarray 'find-face))) + (if (or (null symbol) (and (stringp symbol) (zerop (length symbol)))) + () + (if (stringp symbol) + (setq symbol (intern symbol))) + (unless (symbolp symbol) + (error "Should be a symbol %S" symbol)) + (custom-buffer-create-other-window + (list (list symbol 'custom-face)) + (format "*Customize Face: %s*" (custom-unlispify-tag-name symbol))))) + +;;;###autoload +(defun customize-customized () + "Customize all user options set since the last save in this session." + (interactive) + (let ((found nil)) + (mapatoms (lambda (symbol) + (and (get symbol 'customized-face) + (find-face symbol) + (push (list symbol 'custom-face) found)) + (and (get symbol 'customized-value) + (boundp symbol) + (push (list symbol 'custom-variable) found)))) + (if (not found) + (error "No customized user options") + (custom-buffer-create (custom-sort-items found t nil) + "*Customize Customized*")))) + +;;;###autoload +(defun customize-saved () + "Customize all already saved user options." + (interactive) + (let ((found nil)) + (mapatoms (lambda (symbol) + (and (get symbol 'saved-face) + (find-face symbol) + (push (list symbol 'custom-face) found)) + (and (get symbol 'saved-value) + (boundp symbol) + (push (list symbol 'custom-variable) found)))) + (if (not found ) + (error "No saved user options") + (custom-buffer-create (custom-sort-items found t nil) + "*Customize Saved*")))) + +;;;###autoload +(defun customize-apropos (regexp &optional all) + "Customize all user options matching REGEXP. +If ALL is `options', include only options. +If ALL is `faces', include only faces. +If ALL is `groups', include only groups. +If ALL is t (interactively, with prefix arg), include options which are not +user-settable, as well as faces and groups." + (interactive "sCustomize regexp: \nP") + (let ((found nil)) + (mapatoms (lambda (symbol) + (when (string-match regexp (symbol-name symbol)) + (when (and (not (memq all '(faces options))) + (get symbol 'custom-group)) + (push (list symbol 'custom-group) found)) + (when (and (not (memq all '(options groups))) + (find-face symbol)) + (push (list symbol 'custom-face) found)) + (when (and (not (memq all '(groups faces))) + (boundp symbol) + (or (get symbol 'saved-value) + (get symbol 'standard-value) + (if (memq all '(nil options)) + (user-variable-p symbol) + (get symbol 'variable-documentation)))) + (push (list symbol 'custom-variable) found))))) + (if (not found) + (error "No matches") + (custom-buffer-create (custom-sort-items found t + custom-buffer-order-groups) + "*Customize Apropos*")))) + +;;;###autoload +(defun customize-apropos-options (regexp &optional arg) + "Customize all user options matching REGEXP. +With prefix arg, include options which are not user-settable." + (interactive "sCustomize regexp: \nP") + (customize-apropos regexp (or arg 'options))) + +;;;###autoload +(defun customize-apropos-faces (regexp) + "Customize all user faces matching REGEXP." + (interactive "sCustomize regexp: \n") + (customize-apropos regexp 'faces)) + +;;;###autoload +(defun customize-apropos-groups (regexp) + "Customize all user groups matching REGEXP." + (interactive "sCustomize regexp: \n") + (customize-apropos regexp 'groups)) + + +;;; Buffer. + +(defcustom custom-buffer-style 'links + "Control the presentation style for customization buffers. +The value should be a symbol, one of: + +brackets: groups nest within each other with big horizontal brackets. +links: groups have links to subgroups." + :type '(radio (const :tag "brackets: Groups nest within each others" brackets) + (const :tag "links: Group have links to subgroups" links)) + :group 'custom-buffer) + +(defcustom custom-buffer-indent 3 + "Number of spaces to indent nested groups." + :type 'integer + :group 'custom-buffer) + +;;;###autoload +(defun custom-buffer-create (options &optional name description) + "Create a buffer containing OPTIONS. +Optional NAME is the name of the buffer. +OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where +SYMBOL is a customization option, and WIDGET is a widget for editing +that option." + (unless name (setq name "*Customization*")) + (kill-buffer (get-buffer-create name)) + (switch-to-buffer (get-buffer-create name)) + (custom-buffer-create-internal options description)) + +;;;###autoload +(defun custom-buffer-create-other-window (options &optional name description) + "Create a buffer containing OPTIONS. +Optional NAME is the name of the buffer. +OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where +SYMBOL is a customization option, and WIDGET is a widget for editing +that option." + (unless name (setq name "*Customization*")) + (kill-buffer (get-buffer-create name)) + (let ((window (selected-window))) + (switch-to-buffer-other-window (get-buffer-create name)) + (custom-buffer-create-internal options description) + (select-window window))) + +(defcustom custom-reset-button-menu t + "If non-nil, only show a single reset button in customize buffers. +This button will have a menu with all three reset operations." + :type 'boolean + :group 'custom-buffer) + +(defconst custom-skip-messages 5) + +(defun custom-buffer-create-internal (options &optional description) + (message "Creating customization buffer...") + (custom-mode) + (widget-insert "This is a customization buffer") + (if description + (widget-insert description)) + (widget-insert ".\n\ +Type RET or click button2 on an active field to invoke its action. +Invoke ") + (widget-create 'info-link + :tag "Help" + :help-echo "Read the online help" + "(XEmacs)Easy Customization") + (widget-insert " for more information.\n\n") + (message "Creating customization buttons...") + (widget-insert "Operate on everything in this buffer:\n ") + (widget-create 'push-button + :tag "Set" + :tag-glyph '("set-up" "set-down") + :help-echo "\ +Make your editing in this buffer take effect for this session" + :action (lambda (widget &optional event) + (Custom-set))) + (widget-insert " ") + (widget-create 'push-button + :tag "Save" + :tag-glyph '("save-up" "save-down") + :help-echo "\ +Make your editing in this buffer take effect for future Emacs sessions" + :action (lambda (widget &optional event) + (Custom-save))) + (if custom-reset-button-menu + (progn + (widget-insert " ") + (widget-create 'push-button + :tag "Reset" + :tag-glyph '("reset-up" "reset-down") + :help-echo "Show a menu with reset operations" + :mouse-down-action (lambda (&rest junk) t) + :action (lambda (widget &optional event) + (custom-reset event)))) + (widget-insert " ") + (widget-create 'push-button + :tag "Reset" + :help-echo "\ +Reset all edited text in this buffer to reflect current values" + :action 'Custom-reset-current) + (widget-insert " ") + (widget-create 'push-button + :tag "Reset to Saved" + :help-echo "\ +Reset all values in this buffer to their saved settings" + :action 'Custom-reset-saved) + (widget-insert " ") + (widget-create 'push-button + :tag "Reset to Standard" + :help-echo "\ +Reset all values in this buffer to their standard settings" + :action 'Custom-reset-standard)) + (widget-insert " ") + (widget-create 'push-button + :tag "Done" + :tag-glyph '("done-up" "done-down") + :help-echo "Bury the buffer" + :action (lambda (widget &optional event) + (bury-buffer))) + (widget-insert "\n\n") + (message "Creating customization items...") + (setq custom-options + (if (= (length options) 1) + (mapcar (lambda (entry) + (widget-create (nth 1 entry) + :documentation-shown t + :custom-state 'unknown + :tag (custom-unlispify-tag-name + (nth 0 entry)) + :value (nth 0 entry))) + options) + (let ((count 0) + (length (length options))) + (mapcar (lambda (entry) + (prog2 + (display-message + 'progress + (format "Creating customization items %2d%%..." + (/ (* 100.0 count) length))) + (widget-create (nth 1 entry) + :tag (custom-unlispify-tag-name + (nth 0 entry)) + :value (nth 0 entry)) + (incf count) + (unless (eq (preceding-char) ?\n) + (widget-insert "\n")) + (widget-insert "\n"))) + options)))) + (unless (eq (preceding-char) ?\n) + (widget-insert "\n")) + (display-message 'progress + (format + "Creating customization items %2d%%...done" 100)) + (unless (eq custom-buffer-style 'tree) + (mapc 'custom-magic-reset custom-options)) + (message "Creating customization setup...") + (widget-setup) + (goto-char (point-min)) + (message "Creating customization buffer...done")) + + +;;; The Tree Browser. + +;;;###autoload +(defun customize-browse (&optional group) + "Create a tree browser for the customize hierarchy." + (interactive) + (unless group + (setq group 'emacs)) + (let ((name "*Customize Browser*")) + (kill-buffer (get-buffer-create name)) + (switch-to-buffer (get-buffer-create name))) + (custom-mode) + (widget-insert "\ +Square brackets show active fields; type RET or click button2 +on an active field to invoke its action. +Invoke [+] below to expand a group, and [-] to collapse an expanded group.\n") + (if custom-browse-only-groups + (widget-insert "\ +Invoke the [Group] button below to edit that item in another window.\n\n") + (widget-insert "Invoke the ") + (widget-create 'item + :format "%t" + :tag "[Group]" + :tag-glyph "folder") + (widget-insert ", ") + (widget-create 'item + :format "%t" + :tag "[Face]" + :tag-glyph "face") + (widget-insert ", and ") + (widget-create 'item + :format "%t" + :tag "[Option]" + :tag-glyph "option") + (widget-insert " buttons below to edit that +item in another window.\n\n")) + (let ((custom-buffer-style 'tree)) + (widget-create 'custom-group + :custom-last t + :custom-state 'unknown + :tag (custom-unlispify-tag-name group) + :value group)) + (goto-char (point-min))) + +(define-widget 'custom-browse-visibility 'item + "Control visibility of of items in the customize tree browser." + :format "%[[%t]%]" + :action 'custom-browse-visibility-action) + +(defun custom-browse-visibility-action (widget &rest ignore) + (let ((custom-buffer-style 'tree)) + (custom-toggle-parent widget))) + +(define-widget 'custom-browse-group-tag 'push-button + "Show parent in other window when activated." + :tag "Group" + :tag-glyph "folder" + :action 'custom-browse-group-tag-action) + +(defun custom-browse-group-tag-action (widget &rest ignore) + (let ((parent (widget-get widget :parent))) + (customize-group-other-window (widget-value parent)))) + +(define-widget 'custom-browse-variable-tag 'push-button + "Show parent in other window when activated." + :tag "Option" + :tag-glyph "option" + :action 'custom-browse-variable-tag-action) + +(defun custom-browse-variable-tag-action (widget &rest ignore) + (let ((parent (widget-get widget :parent))) + (customize-variable-other-window (widget-value parent)))) + +(define-widget 'custom-browse-face-tag 'push-button + "Show parent in other window when activated." + :tag "Face" + :tag-glyph "face" + :action 'custom-browse-face-tag-action) + +(defun custom-browse-face-tag-action (widget &rest ignore) + (let ((parent (widget-get widget :parent))) + (customize-face-other-window (widget-value parent)))) + +(defconst custom-browse-alist '((" " "space") + (" | " "vertical") + ("-\\ " "top") + (" |-" "middle") + (" `-" "bottom"))) + +(defun custom-browse-insert-prefix (prefix) + "Insert PREFIX. On XEmacs convert it to line graphics." + ;; ### Unfinished. + (if nil ; (string-match "XEmacs" emacs-version) + (progn + (insert "*") + (while (not (string-equal prefix "")) + (let ((entry (substring prefix 0 3))) + (setq prefix (substring prefix 3)) + (let ((overlay (make-overlay (1- (point)) (point) nil t nil)) + (name (nth 1 (assoc entry custom-browse-alist)))) + (overlay-put overlay 'end-glyph (widget-glyph-find name entry)) + (overlay-put overlay 'start-open t) + (overlay-put overlay 'end-open t))))) + (insert prefix))) + + +;;; Modification of Basic Widgets. +;; +;; We add extra properties to the basic widgets needed here. This is +;; fine, as long as we are careful to stay within out own namespace. +;; +;; We want simple widgets to be displayed by default, but complex +;; widgets to be hidden. + +(widget-put (get 'item 'widget-type) :custom-show t) +(widget-put (get 'editable-field 'widget-type) + :custom-show (lambda (widget value) + (let ((pp (pp-to-string value))) + (cond ((string-match "\n" pp) + nil) + ((> (length pp) 40) + nil) + (t t))))) +(widget-put (get 'menu-choice 'widget-type) :custom-show t) + +;;; The `custom-manual' Widget. + +(define-widget 'custom-manual 'info-link + "Link to the manual entry for this customization option." + :tag "Manual") + +;;; The `custom-magic' Widget. + +(defgroup custom-magic-faces nil + "Faces used by the magic button." + :group 'custom-faces + :group 'custom-buffer) + +(defface custom-invalid-face '((((class color)) + (:foreground "yellow" :background "red")) + (t + (:bold t :italic t :underline t))) + "Face used when the customize item is invalid." + :group 'custom-magic-faces) + +(defface custom-rogue-face '((((class color)) + (:foreground "pink" :background "black")) + (t + (:underline t))) + "Face used when the customize item is not defined for customization." + :group 'custom-magic-faces) + +(defface custom-modified-face '((((class color)) + (:foreground "white" :background "blue")) + (t + (:italic t :bold))) + "Face used when the customize item has been modified." + :group 'custom-magic-faces) + +(defface custom-set-face '((((class color)) + (:foreground "blue" :background "white")) + (t + (:italic t))) + "Face used when the customize item has been set." + :group 'custom-magic-faces) + +(defface custom-changed-face '((((class color)) + (:foreground "white" :background "blue")) + (t + (:italic t))) + "Face used when the customize item has been changed." + :group 'custom-magic-faces) + +(defface custom-saved-face '((t (:underline t))) + "Face used when the customize item has been saved." + :group 'custom-magic-faces) + +(defconst custom-magic-alist '((nil "#" underline "\ +uninitialized, you should not see this.") + (unknown "?" italic "\ +unknown, you should not see this.") + (hidden "-" default "\ +hidden, invoke \"Show\" button in the previous line to show." "\ +group now hidden, invoke the above \"Show\" button to show contents.") + (invalid "x" custom-invalid-face "\ +the value displayed for this %c is invalid and cannot be set.") + (modified "*" custom-modified-face "\ +you have edited the value as text, but you have not set the %c." "\ +you have edited something in this group, but not set it.") + (set "+" custom-set-face "\ +you have set this %c, but not saved it for future sessions." "\ +something in this group has been set, but not saved.") + (changed ":" custom-changed-face "\ +this %c has been changed outside the customize buffer." "\ +something in this group has been changed outside customize.") + (saved "!" custom-saved-face "\ +this %c has been set and saved." "\ +something in this group has been set and saved.") + (rogue "@" custom-rogue-face "\ +this %c has not been changed with customize." "\ +something in this group is not prepared for customization.") + (standard " " nil "\ +this %c is unchanged from its standard setting." "\ +visible group members are all at standard settings.")) + "Alist of customize option states. +Each entry is of the form (STATE MAGIC FACE ITEM-DESC [ GROUP-DESC ]), where + +STATE is one of the following symbols: + +`nil' + For internal use, should never occur. +`unknown' + For internal use, should never occur. +`hidden' + This item is not being displayed. +`invalid' + This item is modified, but has an invalid form. +`modified' + This item is modified, and has a valid form. +`set' + This item has been set but not saved. +`changed' + The current value of this item has been changed temporarily. +`saved' + This item is marked for saving. +`rogue' + This item has no customization information. +`standard' + This item is unchanged from the standard setting. + +MAGIC is a string used to present that state. + +FACE is a face used to present the state. + +ITEM-DESC is a string describing the state for options. + +GROUP-DESC is a string describing the state for groups. If this is +left out, ITEM-DESC will be used. + +The string %c in either description will be replaced with the +category of the item. These are `group'. `option', and `face'. + +The list should be sorted most significant first.") + +(defcustom custom-magic-show 'long + "If non-nil, show textual description of the state. +If `long', show a full-line description, not just one word." + :type '(choice (const :tag "no" nil) + (const short) + (const long)) + :group 'custom-buffer) + +(defcustom custom-magic-show-hidden '(option face) + "Control whether the State button is shown for hidden items. +The value should be a list with the custom categories where the State +button should be visible. Possible categories are `group', `option', +and `face'." + :type '(set (const group) (const option) (const face)) + :group 'custom-buffer) + +(defcustom custom-magic-show-button nil + "Show a \"magic\" button indicating the state of each customization option." + :type 'boolean + :group 'custom-buffer) + +(define-widget 'custom-magic 'default + "Show and manipulate state for a customization option." + :format "%v" + :action 'widget-parent-action + :notify 'ignore + :value-get 'ignore + :value-create 'custom-magic-value-create + :value-delete 'widget-children-value-delete) + +(defun widget-magic-mouse-down-action (widget &optional event) + ;; Non-nil unless hidden. + (not (eq (widget-get (widget-get (widget-get widget :parent) :parent) + :custom-state) + 'hidden))) + +(defun custom-magic-value-create (widget) + ;; Create compact status report for WIDGET. + (let* ((parent (widget-get widget :parent)) + (state (widget-get parent :custom-state)) + (hidden (eq state 'hidden)) + (entry (assq state custom-magic-alist)) + (magic (nth 1 entry)) + (face (nth 2 entry)) + (category (widget-get parent :custom-category)) + (text (or (and (eq category 'group) + (nth 4 entry)) + (nth 3 entry))) + (form (widget-get parent :custom-form)) + children) + (while (string-match "\\`\\(.*\\)%c\\(.*\\)\\'" text) + (setq text (concat (match-string 1 text) + (symbol-name category) + (match-string 2 text)))) + (when (and custom-magic-show + (or (not hidden) + (memq category custom-magic-show-hidden))) + (insert " ") + (when (and (eq category 'group) + (not (and (eq custom-buffer-style 'links) + (> (widget-get parent :custom-level) 1)))) + (insert-char ?\ (* custom-buffer-indent + (widget-get parent :custom-level)))) + (push (widget-create-child-and-convert + widget 'choice-item + :help-echo "Change the state of this item" + :format (if hidden "%t" "%[%t%]") + :button-prefix 'widget-push-button-prefix + :button-suffix 'widget-push-button-suffix + :mouse-down-action 'widget-magic-mouse-down-action + :tag "State" + ;;:tag-glyph (or hidden '("state-up" "state-down")) + ) + children) + (insert ": ") + (let ((start (point))) + (if (eq custom-magic-show 'long) + (insert text) + (insert (symbol-name state))) + (cond ((eq form 'lisp) + (insert " (lisp)")) + ((eq form 'mismatch) + (insert " (mismatch)"))) + (put-text-property start (point) 'face 'custom-state-face)) + (insert "\n")) + (when (and (eq category 'group) + (not (and (eq custom-buffer-style 'links) + (> (widget-get parent :custom-level) 1)))) + (insert-char ?\ (* custom-buffer-indent + (widget-get parent :custom-level)))) + (when custom-magic-show-button + (when custom-magic-show + (let ((indent (widget-get parent :indent))) + (when indent + (insert-char ?\ indent)))) + (push (widget-create-child-and-convert + widget 'choice-item + :mouse-down-action 'widget-magic-mouse-down-action + :button-face face + :button-prefix "" + :button-suffix "" + :help-echo "Change the state" + :format (if hidden "%t" "%[%t%]") + :tag (if (memq form '(lisp mismatch)) + (concat "(" magic ")") + (concat "[" magic "]"))) + children) + (insert " ")) + (widget-put widget :children children))) + +(defun custom-magic-reset (widget) + "Redraw the :custom-magic property of WIDGET." + (let ((magic (widget-get widget :custom-magic))) + (widget-value-set magic (widget-value magic)))) + +;;; The `custom' Widget. + +(defface custom-button-face '((t (:bold t))) + "Face used for buttons in customization buffers." + :group 'custom-faces) + +(defface custom-documentation-face nil + "Face used for documentation strings in customization buffers." + :group 'custom-faces) + +(defface custom-state-face '((((class color) + (background dark)) + (:foreground "lime green")) + (((class color) + (background light)) + (:foreground "dark green")) + (t nil)) + "Face used for State descriptions in the customize buffer." + :group 'custom-faces) + +(define-widget 'custom 'default + "Customize a user option." + :format "%v" + :convert-widget 'custom-convert-widget + :notify 'custom-notify + :custom-prefix "" + :custom-level 1 + :custom-state 'hidden + :documentation-property 'widget-subclass-responsibility + :value-create 'widget-subclass-responsibility + :value-delete 'widget-children-value-delete + :value-get 'widget-value-value-get + :validate 'widget-children-validate + :match (lambda (widget value) (symbolp value))) + +(defun custom-convert-widget (widget) + ;; Initialize :value and :tag from :args in WIDGET. + (let ((args (widget-get widget :args))) + (when args + (widget-put widget :value (widget-apply widget + :value-to-internal (car args))) + (widget-put widget :tag (custom-unlispify-tag-name (car args))) + (widget-put widget :args nil))) + widget) + +(defun custom-notify (widget &rest args) + "Keep track of changes." + (let ((state (widget-get widget :custom-state))) + (unless (eq state 'modified) + (unless (memq state '(nil unknown hidden)) + (widget-put widget :custom-state 'modified)) + (custom-magic-reset widget) + (apply 'widget-default-notify widget args)))) + +(defun custom-redraw (widget) + "Redraw WIDGET with current settings." + (let ((line (count-lines (point-min) (point))) + (column (current-column)) + (pos (point)) + (from (marker-position (widget-get widget :from))) + (to (marker-position (widget-get widget :to)))) + (save-excursion + (widget-value-set widget (widget-value widget)) + (custom-redraw-magic widget)) + (when (and (>= pos from) (<= pos to)) + (condition-case nil + (progn + (if (> column 0) + (goto-line line) + (goto-line (1+ line))) + (move-to-column column)) + (error nil))))) + +(defun custom-redraw-magic (widget) + "Redraw WIDGET state with current settings." + (while widget + (let ((magic (widget-get widget :custom-magic))) + (cond (magic + (widget-value-set magic (widget-value magic)) + (when (setq widget (widget-get widget :group)) + (custom-group-state-update widget))) + (t + (setq widget nil))))) + (widget-setup)) + +(defun custom-show (widget value) + "Non-nil if WIDGET should be shown with VALUE by default." + (let ((show (widget-get widget :custom-show))) + (cond ((null show) + nil) + ((eq t show) + t) + (t + (funcall show widget value))))) + +(defvar custom-load-recursion nil + "Hack to avoid recursive dependencies.") + +(defun custom-load-symbol (symbol) + "Load all dependencies for SYMBOL." + (unless custom-load-recursion + (let ((custom-load-recursion t) + (loads (get symbol 'custom-loads)) + load) + (while loads + (setq load (car loads) + loads (cdr loads)) + (cond ((symbolp load) + (condition-case nil + (require load) + (error nil))) + ;; Don't reload a file already loaded. + ((and (boundp 'preloaded-file-list) + (member load preloaded-file-list))) + ((assoc load load-history)) + ((assoc (locate-library load) load-history)) + (t + (condition-case nil + ;; Without this, we would load cus-edit recursively. + ;; We are still loading it when we call this, + ;; and it is not in load-history yet. + (or (equal load "cus-edit") + (load-library load)) + (error nil)))))))) + +(defun custom-load-widget (widget) + "Load all dependencies for WIDGET." + (custom-load-symbol (widget-value widget))) + +(defun custom-unloaded-symbol-p (symbol) + "Return non-nil if the dependencies of SYMBOL has not yet been loaded." + (let ((found nil) + (loads (get symbol 'custom-loads)) + load) + (while loads + (setq load (car loads) + loads (cdr loads)) + (cond ((symbolp load) + (unless (featurep load) + (setq found t))) + ((assoc load load-history)) + ((assoc (locate-library load) load-history) + ;; #### WTF??? + (message nil)) + (t + (setq found t)))) + found)) + +(defun custom-unloaded-widget-p (widget) + "Return non-nil if the dependencies of WIDGET has not yet been loaded." + (custom-unloaded-symbol-p (widget-value widget))) + +(defun custom-toggle-hide (widget) + "Toggle visibility of WIDGET." + (custom-load-widget widget) + (let ((state (widget-get widget :custom-state))) + (cond ((memq state '(invalid modified)) + (error "There are unset changes")) + ((eq state 'hidden) + (widget-put widget :custom-state 'unknown)) + (t + (widget-put widget :documentation-shown nil) + (widget-put widget :custom-state 'hidden))) + (custom-redraw widget) + (widget-setup))) + +(defun custom-toggle-parent (widget &rest ignore) + "Toggle visibility of parent of WIDGET." + (custom-toggle-hide (widget-get widget :parent))) + +(defun custom-add-see-also (widget &optional prefix) + "Add `See also ...' to WIDGET if there are any links. +Insert PREFIX first if non-nil." + (let* ((symbol (widget-get widget :value)) + (links (get symbol 'custom-links)) + (many (> (length links) 2)) + (buttons (widget-get widget :buttons)) + (indent (widget-get widget :indent))) + (when links + (when indent + (insert-char ?\ indent)) + (when prefix + (insert prefix)) + (insert "See also ") + (while links + (push (widget-create-child-and-convert widget (car links)) + buttons) + (setq links (cdr links)) + (cond ((null links) + (insert ".\n")) + ((null (cdr links)) + (if many + (insert ", and ") + (insert " and "))) + (t + (insert ", ")))) + (widget-put widget :buttons buttons)))) + +(defun custom-add-parent-links (widget &optional initial-string) + "Add \"Parent groups: ...\" to WIDGET if the group has parents. +The value if non-nil if any parents were found. +If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"." + (let ((name (widget-value widget)) + (type (widget-type widget)) + (buttons (widget-get widget :buttons)) + (start (point)) + found) + (insert (or initial-string "Parent groups:")) + (maphash (lambda (group ignore) + (let ((entry (assq name (get group 'custom-group)))) + (when (eq (nth 1 entry) type) + (insert " ") + (push (widget-create-child-and-convert + widget 'custom-group-link + :tag (custom-unlispify-tag-name group) + group) + buttons) + (setq found t)))) + custom-group-hash-table) + (widget-put widget :buttons buttons) + (if found + (insert "\n") + (delete-region start (point))) + found)) + +;;; The `custom-variable' Widget. + +(defface custom-variable-tag-face '((((class color) + (background dark)) + (:foreground "light blue" :underline t)) + (((class color) + (background light)) + (:foreground "blue" :underline t)) + (t (:underline t))) + "Face used for unpushable variable tags." + :group 'custom-faces) + +(defface custom-variable-button-face '((t (:underline t :bold t))) + "Face used for pushable variable tags." + :group 'custom-faces) + +(define-widget 'custom-variable 'custom + "Customize variable." + :format "%v" + :help-echo "Set or reset this variable" + :documentation-property 'variable-documentation + :custom-category 'option + :custom-state nil + :custom-menu 'custom-variable-menu-create + :custom-form 'edit + :value-create 'custom-variable-value-create + :action 'custom-variable-action + :custom-set 'custom-variable-set + :custom-save 'custom-variable-save + :custom-reset-current 'custom-redraw + :custom-reset-saved 'custom-variable-reset-saved + :custom-reset-standard 'custom-variable-reset-standard) + +(defun custom-variable-type (symbol) + "Return a widget suitable for editing the value of SYMBOL. +If SYMBOL has a `custom-type' property, use that. +Otherwise, look up symbol in `custom-guess-type-alist'." + (let* ((type (or (get symbol 'custom-type) + (and (not (get symbol 'standard-value)) + (custom-guess-type symbol)) + 'sexp)) + (options (get symbol 'custom-options)) + (tmp (if (listp type) + (copy-sequence type) + (list type)))) + (when options + (widget-put tmp :options options)) + tmp)) + +(defun custom-variable-value-create (widget) + "Here is where you edit the variables value." + (custom-load-widget widget) + (let* ((buttons (widget-get widget :buttons)) + (children (widget-get widget :children)) + (form (widget-get widget :custom-form)) + (state (widget-get widget :custom-state)) + (symbol (widget-get widget :value)) + (tag (widget-get widget :tag)) + (type (custom-variable-type symbol)) + (conv (widget-convert type)) + (get (or (get symbol 'custom-get) 'default-value)) + (prefix (widget-get widget :custom-prefix)) + (last (widget-get widget :custom-last)) + (value (if (default-boundp symbol) + (funcall get symbol) + (widget-get conv :value)))) + ;; If the widget is new, the child determine whether it is hidden. + (cond (state) + ((custom-show type value) + (setq state 'unknown)) + (t + (setq state 'hidden))) + ;; If we don't know the state, see if we need to edit it in lisp form. + (when (eq state 'unknown) + (unless (widget-apply conv :match value) + ;; (widget-apply (widget-convert type) :match value) + (setq form 'mismatch))) + ;; Now we can create the child widget. + (cond ((eq custom-buffer-style 'tree) + (insert prefix (if last " `--- " " |--- ")) + (push (widget-create-child-and-convert + widget 'custom-browse-variable-tag) + buttons) + (insert " " tag "\n") + (widget-put widget :buttons buttons)) + ((eq state 'hidden) + ;; Indicate hidden value. + (push (widget-create-child-and-convert + widget 'item + :format "%{%t%}: " + :sample-face 'custom-variable-tag-face + :tag tag + :parent widget) + buttons) + (push (widget-create-child-and-convert + widget 'visibility + :help-echo "Show the value of this option" + :action 'custom-toggle-parent + nil) + buttons)) + ((memq form '(lisp mismatch)) + ;; In lisp mode edit the saved value when possible. + (let* ((value (cond ((get symbol 'saved-value) + (car (get symbol 'saved-value))) + ((get symbol 'standard-value) + (car (get symbol 'standard-value))) + ((default-boundp symbol) + (custom-quote (funcall get symbol))) + (t + (custom-quote (widget-get conv :value)))))) + (insert (symbol-name symbol) ": ") + (push (widget-create-child-and-convert + widget 'visibility + :help-echo "Hide the value of this option" + :action 'custom-toggle-parent + t) + buttons) + (insert " ") + (push (widget-create-child-and-convert + widget 'sexp + :button-face 'custom-variable-button-face + :format "%v" + :tag (symbol-name symbol) + :parent widget + :value value) + children))) + (t + ;; Edit mode. + (let* ((format (widget-get type :format)) + tag-format value-format) + (unless (string-match ":" format) + (error "Bad format.")) + (setq tag-format (substring format 0 (match-end 0))) + (setq value-format (substring format (match-end 0))) + (push (widget-create-child-and-convert + widget 'item + :format tag-format + :action 'custom-tag-action + :help-echo "Change value of this option" + :mouse-down-action 'custom-tag-mouse-down-action + :button-face 'custom-variable-button-face + :sample-face 'custom-variable-tag-face + tag) + buttons) + (insert " ") + (push (widget-create-child-and-convert + widget 'visibility + :help-echo "Hide the value of this option" + :action 'custom-toggle-parent + t) + buttons) + (push (widget-create-child-and-convert + widget type + :format value-format + :value value) + children)))) + (unless (eq custom-buffer-style 'tree) + ;; Now update the state. + (unless (eq (preceding-char) ?\n) + (widget-insert "\n")) + (if (eq state 'hidden) + (widget-put widget :custom-state state) + (custom-variable-state-set widget)) + ;; Create the magic button. + (let ((magic (widget-create-child-and-convert + widget 'custom-magic nil))) + (widget-put widget :custom-magic magic) + (push magic buttons)) + ;; Update properties. + (widget-put widget :custom-form form) + (widget-put widget :buttons buttons) + (widget-put widget :children children) + ;; Insert documentation. + (widget-default-format-handler widget ?h) + ;; See also. + (unless (eq state 'hidden) + (when (eq (widget-get widget :custom-level) 1) + (custom-add-parent-links widget)) + (custom-add-see-also widget))))) + +(defun custom-tag-action (widget &rest args) + "Pass :action to first child of WIDGET's parent." + (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children)) + :action args)) + +(defun custom-tag-mouse-down-action (widget &rest args) + "Pass :mouse-down-action to first child of WIDGET's parent." + (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children)) + :mouse-down-action args)) + +(defun custom-variable-state-set (widget) + "Set the state of WIDGET." + (let* ((symbol (widget-value widget)) + (get (or (get symbol 'custom-get) 'default-value)) + (value (if (default-boundp symbol) + (funcall get symbol) + (widget-get widget :value))) + tmp + (state (cond ((setq tmp (get symbol 'customized-value)) + (if (condition-case nil + (equal value (eval (car tmp))) + (error nil)) + 'set + 'changed)) + ((setq tmp (get symbol 'saved-value)) + (if (condition-case nil + (equal value (eval (car tmp))) + (error nil)) + 'saved + 'changed)) + ((setq tmp (get symbol 'standard-value)) + (if (condition-case nil + (equal value (eval (car tmp))) + (error nil)) + 'standard + 'changed)) + (t 'rogue)))) + (widget-put widget :custom-state state))) + +(defvar custom-variable-menu + '(("Set for Current Session" custom-variable-set + (lambda (widget) + (eq (widget-get widget :custom-state) 'modified))) + ("Save for Future Sessions" custom-variable-save + (lambda (widget) + (memq (widget-get widget :custom-state) '(modified set changed rogue)))) + ("Reset to Current" custom-redraw + (lambda (widget) + (and (default-boundp (widget-value widget)) + (memq (widget-get widget :custom-state) '(modified changed))))) + ("Reset to Saved" custom-variable-reset-saved + (lambda (widget) + (and (get (widget-value widget) 'saved-value) + (memq (widget-get widget :custom-state) + '(modified set changed rogue))))) + ("Reset to Standard Settings" custom-variable-reset-standard + (lambda (widget) + (and (get (widget-value widget) 'standard-value) + (memq (widget-get widget :custom-state) + '(modified set changed saved rogue))))) + ("---" ignore ignore) + ("Don't show as Lisp expression" custom-variable-edit + (lambda (widget) + (eq (widget-get widget :custom-form) 'lisp))) + ("Show as Lisp expression" custom-variable-edit-lisp + (lambda (widget) + (eq (widget-get widget :custom-form) 'edit)))) + "Alist of actions for the `custom-variable' widget. +Each entry has the form (NAME ACTION FILTER) where NAME is the name of +the menu entry, ACTION is the function to call on the widget when the +menu is selected, and FILTER is a predicate which takes a `custom-variable' +widget as an argument, and returns non-nil if ACTION is valid on that +widget. If FILTER is nil, ACTION is always valid.") + +(defun custom-variable-action (widget &optional event) + "Show the menu for `custom-variable' WIDGET. +Optional EVENT is the location for the menu." + (if (eq (widget-get widget :custom-state) 'hidden) + (custom-toggle-hide widget) + (unless (eq (widget-get widget :custom-state) 'modified) + (custom-variable-state-set widget)) + ;; Redrawing magic also depresses the state glyph. + ;(custom-redraw-magic widget) + (let* ((completion-ignore-case t) + (answer (widget-choose (concat "Operation on " + (custom-unlispify-tag-name + (widget-get widget :value))) + (custom-menu-filter custom-variable-menu + widget) + event))) + (if answer + (funcall answer widget))))) + +(defun custom-variable-edit (widget) + "Edit value of WIDGET." + (widget-put widget :custom-state 'unknown) + (widget-put widget :custom-form 'edit) + (custom-redraw widget)) + +(defun custom-variable-edit-lisp (widget) + "Edit the lisp representation of the value of WIDGET." + (widget-put widget :custom-state 'unknown) + (widget-put widget :custom-form 'lisp) + (custom-redraw widget)) + +(defun custom-variable-set (widget) + "Set the current value for the variable being edited by WIDGET." + (let* ((form (widget-get widget :custom-form)) + (state (widget-get widget :custom-state)) + (child (car (widget-get widget :children))) + (symbol (widget-value widget)) + (set (or (get symbol 'custom-set) 'set-default)) + val) + (cond ((eq state 'hidden) + (error "Cannot set hidden variable.")) + ((setq val (widget-apply child :validate)) + (goto-char (widget-get val :from)) + (error "%s" (widget-get val :error))) + ((memq form '(lisp mismatch)) + (funcall set symbol (eval (setq val (widget-value child)))) + (put symbol 'customized-value (list val))) + (t + (funcall set symbol (setq val (widget-value child))) + (put symbol 'customized-value (list (custom-quote val))))) + (custom-variable-state-set widget) + (custom-redraw-magic widget))) + +(defun custom-variable-save (widget) + "Set and save the value for the variable being edited by WIDGET." + (let* ((form (widget-get widget :custom-form)) + (state (widget-get widget :custom-state)) + (child (car (widget-get widget :children))) + (symbol (widget-value widget)) + (set (or (get symbol 'custom-set) 'set-default)) + val) + (cond ((eq state 'hidden) + (error "Cannot set hidden variable.")) + ((setq val (widget-apply child :validate)) + (goto-char (widget-get val :from)) + (error "%s" (widget-get val :error))) + ((memq form '(lisp mismatch)) + (put symbol 'saved-value (list (widget-value child))) + (funcall set symbol (eval (widget-value child)))) + (t + (put symbol + 'saved-value (list (custom-quote (widget-value + child)))) + (funcall set symbol (widget-value child)))) + (put symbol 'customized-value nil) + (custom-save-all) + (custom-variable-state-set widget) + (custom-redraw-magic widget))) + +(defun custom-variable-reset-saved (widget) + "Restore the saved value for the variable being edited by WIDGET." + (let* ((symbol (widget-value widget)) + (set (or (get symbol 'custom-set) 'set-default))) + (if (get symbol 'saved-value) + (condition-case nil + (funcall set symbol (eval (car (get symbol 'saved-value)))) + (error nil)) + (error "No saved value for %s" symbol)) + (put symbol 'customized-value nil) + (widget-put widget :custom-state 'unknown) + (custom-redraw widget))) + +(defun custom-variable-reset-standard (widget) + "Restore the standard setting for the variable being edited by WIDGET." + (let* ((symbol (widget-value widget)) + (set (or (get symbol 'custom-set) 'set-default))) + (if (get symbol 'standard-value) + (funcall set symbol (eval (car (get symbol 'standard-value)))) + (error "No standard setting known for %S" symbol)) + (put symbol 'customized-value nil) + (when (get symbol 'saved-value) + (put symbol 'saved-value nil) + (custom-save-all)) + (widget-put widget :custom-state 'unknown) + (custom-redraw widget))) + +;;; The `custom-face-edit' Widget. + +(define-widget 'custom-face-edit 'checklist + "Edit face attributes." + :format "%t: %v" + :tag "Attributes" + :extra-offset 12 + :button-args '(:help-echo "Control whether this attribute have any effect") + :args (mapcar (lambda (att) + (list 'group + :inline t + :sibling-args (widget-get (nth 1 att) :sibling-args) + (list 'const :format "" :value (nth 0 att)) + (nth 1 att))) + custom-face-attributes)) + +;;; The `custom-display' Widget. + +(define-widget 'custom-display 'menu-choice + "Select a display type." + :tag "Display" + :value t + :help-echo "Specify frames where the face attributes should be used" + :args '((const :tag "all" t) + (checklist + :offset 0 + :extra-offset 9 + :args ((group :sibling-args (:help-echo "\ +Only match the specified window systems") + (const :format "Type: " + type) + (checklist :inline t + :offset 0 + (const :format "X " + :sibling-args (:help-echo "\ +The X11 Window System") + x) + (const :format "PM " + :sibling-args (:help-echo "\ +OS/2 Presentation Manager") + pm) + (const :format "Win32 " + :sibling-args (:help-echo "\ +Windows NT/95/97") + win32) + (const :format "DOS " + :sibling-args (:help-echo "\ +Plain MS-DOS") + pc) + (const :format "TTY%n" + :sibling-args (:help-echo "\ +Plain text terminals") + tty))) + (group :sibling-args (:help-echo "\ +Only match the frames with the specified color support") + (const :format "Class: " + class) + (checklist :inline t + :offset 0 + (const :format "Color " + :sibling-args (:help-echo "\ +Match color frames") + color) + (const :format "Grayscale " + :sibling-args (:help-echo "\ +Match grayscale frames") + grayscale) + (const :format "Monochrome%n" + :sibling-args (:help-echo "\ +Match frames with no color support") + mono))) + (group :sibling-args (:help-echo "\ +Only match frames with the specified intensity") + (const :format "\ +Background brightness: " + background) + (checklist :inline t + :offset 0 + (const :format "Light " + :sibling-args (:help-echo "\ +Match frames with light backgrounds") + light) + (const :format "Dark\n" + :sibling-args (:help-echo "\ +Match frames with dark backgrounds") + dark))))))) + +;;; The `custom-face' Widget. + +(defface custom-face-tag-face '((t (:underline t))) + "Face used for face tags." + :group 'custom-faces) + +(define-widget 'custom-face 'custom + "Customize face." + :sample-face 'custom-face-tag-face + :help-echo "Set or reset this face" + :documentation-property '(lambda (face) + (face-doc-string face)) + :value-create 'custom-face-value-create + :action 'custom-face-action + :custom-category 'face + :custom-form 'selected + :custom-set 'custom-face-set + :custom-save 'custom-face-save + :custom-reset-current 'custom-redraw + :custom-reset-saved 'custom-face-reset-saved + :custom-reset-standard 'custom-face-reset-standard + :custom-menu 'custom-face-menu-create) + +(define-widget 'custom-face-all 'editable-list + "An editable list of display specifications and attributes." + :entry-format "%i %d %v" + :insert-button-args '(:help-echo "Insert new display specification here") + :append-button-args '(:help-echo "Append new display specification here") + :delete-button-args '(:help-echo "Delete this display specification") + :args '((group :format "%v" custom-display custom-face-edit))) + +(defconst custom-face-all (widget-convert 'custom-face-all) + "Converted version of the `custom-face-all' widget.") + +(define-widget 'custom-display-unselected 'item + "A display specification that doesn't match the selected display." + :match 'custom-display-unselected-match) + +(defun custom-display-unselected-match (widget value) + "Non-nil if VALUE is an unselected display specification." + (not (face-spec-set-match-display value (selected-frame)))) + +(define-widget 'custom-face-selected 'group + "Edit the attributes of the selected display in a face specification." + :args '((repeat :format "" + :inline t + (group custom-display-unselected sexp)) + (group (sexp :format "") custom-face-edit) + (repeat :format "" + :inline t + sexp))) + +(defconst custom-face-selected (widget-convert 'custom-face-selected) + "Converted version of the `custom-face-selected' widget.") + +(defun custom-face-value-create (widget) + "Create a list of the display specifications for WIDGET." + (let ((buttons (widget-get widget :buttons)) + (symbol (widget-get widget :value)) + (tag (widget-get widget :tag)) + (state (widget-get widget :custom-state)) + (begin (point)) + (is-last (widget-get widget :custom-last)) + (prefix (widget-get widget :custom-prefix))) + (unless tag + (setq tag (prin1-to-string symbol))) + (cond ((eq custom-buffer-style 'tree) + (insert prefix (if is-last " `--- " " |--- ")) + (push (widget-create-child-and-convert + widget 'custom-browse-face-tag) + buttons) + (insert " " tag "\n") + (widget-put widget :buttons buttons)) + (t + ;; Create tag. + (insert tag) + (if (eq custom-buffer-style 'face) + (insert " ") + (widget-specify-sample widget begin (point)) + (insert ": ")) + ;; Sample. + (and (not (find-face symbol)) + ;; XEmacs cannot display uninitialized faces. + (make-face symbol)) + (push (widget-create-child-and-convert widget 'item + :format "(%{%t%})" + :sample-face symbol + :tag "sample") + buttons) + ;; Visibility. + (insert " ") + (push (widget-create-child-and-convert + widget 'visibility + :help-echo "Hide or show this face" + :action 'custom-toggle-parent + (not (eq state 'hidden))) + buttons) + ;; Magic. + (insert "\n") + (let ((magic (widget-create-child-and-convert + widget 'custom-magic nil))) + (widget-put widget :custom-magic magic) + (push magic buttons)) + ;; Update buttons. + (widget-put widget :buttons buttons) + ;; Insert documentation. + (widget-default-format-handler widget ?h) + ;; See also. + (unless (eq state 'hidden) + (when (eq (widget-get widget :custom-level) 1) + (custom-add-parent-links widget)) + (custom-add-see-also widget)) + ;; Editor. + (unless (eq (preceding-char) ?\n) + (insert "\n")) + (unless (eq state 'hidden) + (message "Creating face editor...") + (custom-load-widget widget) + (let* ((symbol (widget-value widget)) + (spec (or (get symbol 'saved-face) + (get symbol 'face-defface-spec) + ;; Attempt to construct it. + (list (list t (face-custom-attributes-get + symbol (selected-frame)))))) + (form (widget-get widget :custom-form)) + (indent (widget-get widget :indent)) + (edit (widget-create-child-and-convert + widget + (cond ((and (eq form 'selected) + (widget-apply custom-face-selected + :match spec)) + (when indent (insert-char ?\ indent)) + 'custom-face-selected) + ((and (not (eq form 'lisp)) + (widget-apply custom-face-all + :match spec)) + 'custom-face-all) + (t + (when indent (insert-char ?\ indent)) + 'sexp)) + :value spec))) + (custom-face-state-set widget) + (widget-put widget :children (list edit))) + (message "Creating face editor...done")))))) + +(defvar custom-face-menu + '(("Set for Current Session" custom-face-set) + ("Save for Future Sessions" custom-face-save) + ("Reset to Saved" custom-face-reset-saved + (lambda (widget) + (get (widget-value widget) 'saved-face))) + ("Reset to Standard Setting" custom-face-reset-standard + (lambda (widget) + (get (widget-value widget) 'face-defface-spec))) + ("---" ignore ignore) + ("Show all display specs" custom-face-edit-all + (lambda (widget) + (not (eq (widget-get widget :custom-form) 'all)))) + ("Just current attributes" custom-face-edit-selected + (lambda (widget) + (not (eq (widget-get widget :custom-form) 'selected)))) + ("Show as Lisp expression" custom-face-edit-lisp + (lambda (widget) + (not (eq (widget-get widget :custom-form) 'lisp))))) + "Alist of actions for the `custom-face' widget. +Each entry has the form (NAME ACTION FILTER) where NAME is the name of +the menu entry, ACTION is the function to call on the widget when the +menu is selected, and FILTER is a predicate which takes a `custom-face' +widget as an argument, and returns non-nil if ACTION is valid on that +widget. If FILTER is nil, ACTION is always valid.") + +(defun custom-face-edit-selected (widget) + "Edit selected attributes of the value of WIDGET." + (widget-put widget :custom-state 'unknown) + (widget-put widget :custom-form 'selected) + (custom-redraw widget)) + +(defun custom-face-edit-all (widget) + "Edit all attributes of the value of WIDGET." + (widget-put widget :custom-state 'unknown) + (widget-put widget :custom-form 'all) + (custom-redraw widget)) + +(defun custom-face-edit-lisp (widget) + "Edit the lisp representation of the value of WIDGET." + (widget-put widget :custom-state 'unknown) + (widget-put widget :custom-form 'lisp) + (custom-redraw widget)) + +(defun custom-face-state-set (widget) + "Set the state of WIDGET." + (let ((symbol (widget-value widget))) + (widget-put widget :custom-state (cond ((get symbol 'customized-face) + 'set) + ((get symbol 'saved-face) + 'saved) + ((get symbol 'face-defface-spec) + 'standard) + (t + 'rogue))))) + +(defun custom-face-action (widget &optional event) + "Show the menu for `custom-face' WIDGET. +Optional EVENT is the location for the menu." + (if (eq (widget-get widget :custom-state) 'hidden) + (custom-toggle-hide widget) + (let* ((completion-ignore-case t) + (symbol (widget-get widget :value)) + (answer (widget-choose (concat "Operation on " + (custom-unlispify-tag-name symbol)) + (custom-menu-filter custom-face-menu + widget) + event))) + (if answer + (funcall answer widget))))) + +(defun custom-face-set (widget) + "Make the face attributes in WIDGET take effect." + (let* ((symbol (widget-value widget)) + (child (car (widget-get widget :children))) + (value (widget-value child))) + (put symbol 'customized-face value) + (face-spec-set symbol value) + (custom-face-state-set widget) + (custom-redraw-magic widget))) + +(defun custom-face-save (widget) + "Make the face attributes in WIDGET default." + (let* ((symbol (widget-value widget)) + (child (car (widget-get widget :children))) + (value (widget-value child))) + (face-spec-set symbol value) + (put symbol 'saved-face value) + (put symbol 'customized-face nil) + (custom-face-state-set widget) + (custom-redraw-magic widget))) + +(defun custom-face-reset-saved (widget) + "Restore WIDGET to the face's default attributes." + (let* ((symbol (widget-value widget)) + (child (car (widget-get widget :children))) + (value (get symbol 'saved-face))) + (unless value + (error "No saved value for this face")) + (put symbol 'customized-face nil) + (face-spec-set symbol value) + (widget-value-set child value) + (custom-face-state-set widget) + (custom-redraw-magic widget))) + +(defun custom-face-reset-standard (widget) + "Restore WIDGET to the face's standard settings." + (let* ((symbol (widget-value widget)) + (child (car (widget-get widget :children))) + (value (get symbol 'face-defface-spec))) + (unless value + (error "No standard setting for this face")) + (put symbol 'customized-face nil) + (when (get symbol 'saved-face) + (put symbol 'saved-face nil) + (custom-save-all)) + (face-spec-set symbol value) + (widget-value-set child value) + (custom-face-state-set widget) + (custom-redraw-magic widget))) + +;;; The `face' Widget. + +(define-widget 'face 'default + "Select and customize a face." + :convert-widget 'widget-value-convert-widget + :button-prefix 'widget-push-button-prefix + :button-suffix 'widget-push-button-suffix + :format "%t: %[select face%] %v" + :tag "Face" + :value 'default + :value-create 'widget-face-value-create + :value-delete 'widget-face-value-delete + :value-get 'widget-value-value-get + :validate 'widget-children-validate + :action 'widget-face-action + :match (lambda (widget value) (symbolp value))) + +(defun widget-face-value-create (widget) + ;; Create a `custom-face' child. + (let* ((symbol (widget-value widget)) + (custom-buffer-style 'face) + (child (widget-create-child-and-convert + widget 'custom-face + :custom-level nil + :value symbol))) + (custom-magic-reset child) + (setq custom-options (cons child custom-options)) + (widget-put widget :children (list child)))) + +(defun widget-face-value-delete (widget) + ;; Remove the child from the options. + (let ((child (car (widget-get widget :children)))) + (setq custom-options (delq child custom-options)) + (widget-children-value-delete widget))) + +(defvar face-history nil + "History of entered face names.") + +(defun widget-face-action (widget &optional event) + "Prompt for a face." + (let ((answer (completing-read "Face: " + (mapcar (lambda (face) + (list (symbol-name face))) + (face-list)) + nil nil nil + 'face-history))) + (unless (zerop (length answer)) + (widget-value-set widget (intern answer)) + (widget-apply widget :notify widget event) + (widget-setup)))) + +;;; The `hook' Widget. + +(define-widget 'hook 'list + "A emacs lisp hook" + :value-to-internal (lambda (widget value) + (if (symbolp value) + (list value) + value)) + :match (lambda (widget value) + (or (symbolp value) + (widget-group-match widget value))) + :convert-widget 'custom-hook-convert-widget + :tag "Hook") + +(defun custom-hook-convert-widget (widget) + ;; Handle `:custom-options'. + (let* ((options (widget-get widget :options)) + (other `(editable-list :inline t + :entry-format "%i %d%v" + (function :format " %v"))) + (args (if options + (list `(checklist :inline t + ,@(mapcar (lambda (entry) + `(function-item ,entry)) + options)) + other) + (list other)))) + (widget-put widget :args args) + widget)) + +;;; The `custom-group-link' Widget. + +(define-widget 'custom-group-link 'link + "Show parent in other window when activated." + :help-echo 'custom-group-link-help-echo + :action 'custom-group-link-action) + +(defun custom-group-link-help-echo (widget) + (concat "Create customization buffer for the `" + (custom-unlispify-tag-name (widget-value widget)) + "' group")) + +(defun custom-group-link-action (widget &rest ignore) + (customize-group (widget-value widget))) + +;;; The `custom-group' Widget. + +(defcustom custom-group-tag-faces nil + ;; In XEmacs, this ought to play games with font size. + "Face used for group tags. +The first member is used for level 1 groups, the second for level 2, +and so forth. The remaining group tags are shown with +`custom-group-tag-face'." + :type '(repeat face) + :group 'custom-faces) + +(defface custom-group-tag-face-1 '((((class color) + (background dark)) + (:foreground "pink" :underline t)) + (((class color) + (background light)) + (:foreground "red" :underline t)) + (t (:underline t))) + "Face used for group tags.") + +(defface custom-group-tag-face '((((class color) + (background dark)) + (:foreground "light blue" :underline t)) + (((class color) + (background light)) + (:foreground "blue" :underline t)) + (t (:underline t))) + "Face used for low level group tags." + :group 'custom-faces) + +(define-widget 'custom-group 'custom + "Customize group." + :format "%v" + :sample-face-get 'custom-group-sample-face-get + :documentation-property 'group-documentation + :help-echo "Set or reset all members of this group" + :value-create 'custom-group-value-create + :action 'custom-group-action + :custom-category 'group + :custom-set 'custom-group-set + :custom-save 'custom-group-save + :custom-reset-current 'custom-group-reset-current + :custom-reset-saved 'custom-group-reset-saved + :custom-reset-standard 'custom-group-reset-standard + :custom-menu 'custom-group-menu-create) + +(defun custom-group-sample-face-get (widget) + ;; Use :sample-face. + (or (nth (1- (widget-get widget :custom-level)) custom-group-tag-faces) + 'custom-group-tag-face)) + +(define-widget 'custom-group-visibility 'visibility + "An indicator and manipulator for hidden group contents." + :create 'custom-group-visibility-create) + +(defun custom-group-visibility-create (widget) + (let ((visible (widget-value widget))) + (if visible + (insert "--------"))) + (widget-default-create widget)) + +(defun custom-group-members (symbol groups-only) + "Return SYMBOL's custom group members. +If GROUPS-ONLY non-nil, return only those members that are groups." + (if (not groups-only) + (get symbol 'custom-group) + (let (members) + (dolist (entry (get symbol 'custom-group) (nreverse members)) + (when (eq (nth 1 entry) 'custom-group) + (push entry members)))))) + +(defun custom-group-value-create (widget) + "Insert a customize group for WIDGET in the current buffer." + (let* ((state (widget-get widget :custom-state)) + (level (widget-get widget :custom-level)) + ;; (indent (widget-get widget :indent)) + (prefix (widget-get widget :custom-prefix)) + (buttons (widget-get widget :buttons)) + (tag (widget-get widget :tag)) + (symbol (widget-value widget)) + (members (custom-group-members symbol + (and (eq custom-buffer-style 'tree) + custom-browse-only-groups)))) + (cond ((and (eq custom-buffer-style 'tree) + (eq state 'hidden) + (or members (custom-unloaded-widget-p widget))) + (custom-browse-insert-prefix prefix) + (push (widget-create-child-and-convert + widget 'custom-browse-visibility + ;; :tag-glyph "plus" + :tag "+") + buttons) + (insert "-- ") + ;; (widget-glyph-insert nil "-- " "horizontal") + (push (widget-create-child-and-convert + widget 'custom-browse-group-tag) + buttons) + (insert " " tag "\n") + (widget-put widget :buttons buttons)) + ((and (eq custom-buffer-style 'tree) + (zerop (length members))) + (custom-browse-insert-prefix prefix) + (insert "[ ]-- ") + ;; (widget-glyph-insert nil "[ ]" "empty") + ;; (widget-glyph-insert nil "-- " "horizontal") + (push (widget-create-child-and-convert + widget 'custom-browse-group-tag) + buttons) + (insert " " tag "\n") + (widget-put widget :buttons buttons)) + ((eq custom-buffer-style 'tree) + (custom-browse-insert-prefix prefix) + (custom-load-widget widget) + (if (zerop (length members)) + (progn + (custom-browse-insert-prefix prefix) + (insert "[ ]-- ") + ;; (widget-glyph-insert nil "[ ]" "empty") + ;; (widget-glyph-insert nil "-- " "horizontal") + (push (widget-create-child-and-convert + widget 'custom-browse-group-tag) + buttons) + (insert " " tag "\n") + (widget-put widget :buttons buttons)) + (push (widget-create-child-and-convert + widget 'custom-browse-visibility + ;; :tag-glyph "minus" + :tag "-") + buttons) + (insert "-\\ ") + ;; (widget-glyph-insert nil "-\\ " "top") + (push (widget-create-child-and-convert + widget 'custom-browse-group-tag) + buttons) + (insert " " tag "\n") + (widget-put widget :buttons buttons) + (message "Creating group...") + (let* ((members (custom-sort-items members + custom-browse-sort-alphabetically + custom-browse-order-groups)) + (prefixes (widget-get widget :custom-prefixes)) + (custom-prefix-list (custom-prefix-add symbol prefixes)) + (extra-prefix (if (widget-get widget :custom-last) + " " + " | ")) + (prefix (concat prefix extra-prefix)) + children entry) + (while members + (setq entry (car members) + members (cdr members)) + (push (widget-create-child-and-convert + widget (nth 1 entry) + :group widget + :tag (custom-unlispify-tag-name (nth 0 entry)) + :custom-prefixes custom-prefix-list + :custom-level (1+ level) + :custom-last (null members) + :value (nth 0 entry) + :custom-prefix prefix) + children)) + (widget-put widget :children (reverse children))) + (message "Creating group...done"))) + ;; Nested style. + ((eq state 'hidden) + ;; Create level indicator. + (unless (eq custom-buffer-style 'links) + (insert-char ?\ (* custom-buffer-indent (1- level))) + (insert "-- ")) + ;; Create link indicator. + (when (eq custom-buffer-style 'links) + (insert " ") + (push (widget-create-child-and-convert + widget 'custom-group-link + :tag "Open" + :tag-glyph '("open-up" "open-down") + symbol) + buttons) + (insert " ")) + ;; Create tag. + (let ((begin (point))) + (insert tag) + (widget-specify-sample widget begin (point))) + (insert " group") + ;; Create visibility indicator. + (unless (eq custom-buffer-style 'links) + (insert ": ") + (push (widget-create-child-and-convert + widget 'custom-group-visibility + :help-echo "Show members of this group" + :action 'custom-toggle-parent + (not (eq state 'hidden))) + buttons)) + (insert " \n") + ;; Create magic button. + (let ((magic (widget-create-child-and-convert + widget 'custom-magic nil))) + (widget-put widget :custom-magic magic) + (push magic buttons)) + ;; Update buttons. + (widget-put widget :buttons buttons) + ;; Insert documentation. + (if (and (eq custom-buffer-style 'links) (> level 1)) + (widget-put widget :documentation-indent 0)) + (widget-default-format-handler widget ?h)) + ;; Nested style. + (t ;Visible. + (custom-load-widget widget) + ;; Update members + (setq members (custom-group-members + symbol (and (eq custom-buffer-style 'tree) + custom-browse-only-groups))) + ;; Add parent groups references above the group. + (if t ;;; This should test that the buffer + ;;; was made to display a group. + (when (eq level 1) + (if (custom-add-parent-links widget + "Go to parent group:") + (insert "\n")))) + ;; Create level indicator. + (insert-char ?\ (* custom-buffer-indent (1- level))) + (insert "/- ") + ;; Create tag. + (let ((start (point))) + (insert tag) + (widget-specify-sample widget start (point))) + (insert " group: ") + ;; Create visibility indicator. + (unless (eq custom-buffer-style 'links) + (insert "--------") + (push (widget-create-child-and-convert + widget 'visibility + :help-echo "Hide members of this group" + :action 'custom-toggle-parent + (not (eq state 'hidden))) + buttons) + (insert " ")) + ;; Create more dashes. + ;; Use 76 instead of 75 to compensate for the temporary "<" + ;; added by `widget-insert'. + (insert-char ?- (- 76 (current-column) + (* custom-buffer-indent level))) + (insert "\\\n") + ;; Create magic button. + (let ((magic (widget-create-child-and-convert + widget 'custom-magic + :indent 0 + nil))) + (widget-put widget :custom-magic magic) + (push magic buttons)) + ;; Update buttons. + (widget-put widget :buttons buttons) + ;; Insert documentation. + (widget-default-format-handler widget ?h) + ;; Parent groups. + (if nil ;;; This should test that the buffer + ;;; was not made to display a group. + (when (eq level 1) + (insert-char ?\ custom-buffer-indent) + (custom-add-parent-links widget))) + (custom-add-see-also widget + (make-string (* custom-buffer-indent level) + ?\ )) + ;; Members. + (message "Creating group...") + (let* ((members (custom-sort-items members + custom-buffer-sort-alphabetically + custom-buffer-order-groups)) + (prefixes (widget-get widget :custom-prefixes)) + (custom-prefix-list (custom-prefix-add symbol prefixes)) + (length (length members)) + (count 0) + (children (mapcar + (lambda (entry) + (widget-insert "\n") + (when (zerop (% count custom-skip-messages)) + (display-message + 'progress + (format "\ +Creating group members... %2d%%" + (/ (* 100.0 count) length)))) + (incf count) + (prog1 + (widget-create-child-and-convert + widget (nth 1 entry) + :group widget + :tag (custom-unlispify-tag-name + (nth 0 entry)) + :custom-prefixes custom-prefix-list + :custom-level (1+ level) + :value (nth 0 entry)) + (unless (eq (preceding-char) ?\n) + (widget-insert "\n")))) + members))) + (message "Creating group magic...") + (mapc 'custom-magic-reset children) + (message "Creating group state...") + (widget-put widget :children children) + (custom-group-state-update widget) + (message "Creating group... done")) + ;; End line + (insert "\n") + (insert-char ?\ (* custom-buffer-indent (1- level))) + (insert "\\- " (widget-get widget :tag) " group end ") + (insert-char ?- (- 75 (current-column) (* custom-buffer-indent level))) + (insert "/\n"))))) + +(defvar custom-group-menu + '(("Set for Current Session" custom-group-set + (lambda (widget) + (eq (widget-get widget :custom-state) 'modified))) + ("Save for Future Sessions" custom-group-save + (lambda (widget) + (memq (widget-get widget :custom-state) '(modified set)))) + ("Reset to Current" custom-group-reset-current + (lambda (widget) + (memq (widget-get widget :custom-state) '(modified)))) + ("Reset to Saved" custom-group-reset-saved + (lambda (widget) + (memq (widget-get widget :custom-state) '(modified set)))) + ("Reset to standard setting" custom-group-reset-standard + (lambda (widget) + (memq (widget-get widget :custom-state) '(modified set saved))))) + "Alist of actions for the `custom-group' widget. +Each entry has the form (NAME ACTION FILTER) where NAME is the name of +the menu entry, ACTION is the function to call on the widget when the +menu is selected, and FILTER is a predicate which takes a `custom-group' +widget as an argument, and returns non-nil if ACTION is valid on that +widget. If FILTER is nil, ACTION is always valid.") + +(defun custom-group-action (widget &optional event) + "Show the menu for `custom-group' WIDGET. +Optional EVENT is the location for the menu." + (if (eq (widget-get widget :custom-state) 'hidden) + (custom-toggle-hide widget) + (let* ((completion-ignore-case t) + (answer (widget-choose (concat "Operation on " + (custom-unlispify-tag-name + (widget-get widget :value))) + (custom-menu-filter custom-group-menu + widget) + event))) + (if answer + (funcall answer widget))))) + +(defun custom-group-set (widget) + "Set changes in all modified group members." + (let ((children (widget-get widget :children))) + (mapc (lambda (child) + (when (eq (widget-get child :custom-state) 'modified) + (widget-apply child :custom-set))) + children))) + +(defun custom-group-save (widget) + "Save all modified group members." + (let ((children (widget-get widget :children))) + (mapc (lambda (child) + (when (memq (widget-get child :custom-state) '(modified set)) + (widget-apply child :custom-save))) + children))) + +(defun custom-group-reset-current (widget) + "Reset all modified group members." + (let ((children (widget-get widget :children))) + (mapc (lambda (child) + (when (eq (widget-get child :custom-state) 'modified) + (widget-apply child :custom-reset-current))) + children))) + +(defun custom-group-reset-saved (widget) + "Reset all modified or set group members." + (let ((children (widget-get widget :children))) + (mapc (lambda (child) + (when (memq (widget-get child :custom-state) '(modified set)) + (widget-apply child :custom-reset-saved))) + children))) + +(defun custom-group-reset-standard (widget) + "Reset all modified, set, or saved group members." + (let ((children (widget-get widget :children))) + (mapc (lambda (child) + (when (memq (widget-get child :custom-state) + '(modified set saved)) + (widget-apply child :custom-reset-standard))) + children))) + +(defun custom-group-state-update (widget) + "Update magic." + (unless (eq (widget-get widget :custom-state) 'hidden) + (let* ((children (widget-get widget :children)) + (states (mapcar (lambda (child) + (widget-get child :custom-state)) + children)) + (magics custom-magic-alist) + (found 'standard)) + (while magics + (let ((magic (car (car magics)))) + (if (and (not (eq magic 'hidden)) + (memq magic states)) + (setq found magic + magics nil) + (setq magics (cdr magics))))) + (widget-put widget :custom-state found))) + (custom-magic-reset widget)) + +;;; The `custom-save-all' Function. +;;;###autoload +(defcustom custom-file (if (boundp 'emacs-user-extension-dir) + (concat "~" + init-file-user + emacs-user-extension-dir + "options.el") + "~/.emacs") + "File used for storing customization information. +If you change this from the default \"~/.emacs\" you need to +explicitly load that file for the settings to take effect." + :type 'file + :group 'customize) + +(defun custom-save-delete (symbol) + "Delete the call to SYMBOL form `custom-file'. +Leave point at the location of the call, or after the last expression." + (let ((find-file-hooks nil) + (auto-mode-alist nil)) + (set-buffer (find-file-noselect custom-file))) + (goto-char (point-min)) + (catch 'found + (while t + (let ((sexp (condition-case nil + (read (current-buffer)) + (end-of-file (throw 'found nil))))) + (when (and (listp sexp) + (eq (car sexp) symbol)) + (delete-region (save-excursion + (backward-sexp) + (point)) + (point)) + (throw 'found nil)))))) + +(defun custom-save-variables () + "Save all customized variables in `custom-file'." + (save-excursion + (custom-save-delete 'custom-set-variables) + (let ((standard-output (current-buffer))) + (unless (bolp) + (princ "\n")) + (princ "(custom-set-variables") + (mapatoms (lambda (symbol) + (let ((value (get symbol 'saved-value)) + (requests (get symbol 'custom-requests)) + (now (not (or (get symbol 'standard-value) + (and (not (boundp symbol)) + (not (get symbol 'force-value))))))) + (when value + (princ "\n '(") + (princ symbol) + (princ " ") + (prin1 (car value)) + (cond (requests + (if now + (princ " t ") + (princ " nil ")) + (prin1 requests) + (princ ")")) + (now + (princ " t)")) + (t + (princ ")"))))))) + (princ ")") + (unless (looking-at "\n") + (princ "\n"))))) + +(defun custom-save-faces () + "Save all customized faces in `custom-file'." + (save-excursion + (custom-save-delete 'custom-set-faces) + (let ((standard-output (current-buffer))) + (unless (bolp) + (princ "\n")) + (princ "(custom-set-faces") + (let ((value (get 'default 'saved-face))) + ;; The default face must be first, since it affects the others. + (when value + (princ "\n '(default ") + (prin1 value) + (if (or (get 'default 'face-defface-spec) + (and (not (find-face 'default)) + (not (get 'default 'force-face)))) + (princ ")") + (princ " t)")))) + (mapatoms (lambda (symbol) + (let ((value (get symbol 'saved-face))) + (when (and (not (eq symbol 'default)) + ;; Don't print default face here. + value) + (princ "\n '(") + (princ symbol) + (princ " ") + (prin1 value) + (if (or (get symbol 'face-defface-spec) + (and (not (find-face symbol)) + (not (get symbol 'force-face)))) + (princ ")") + (princ " t)")))))) + (princ ")") + (unless (looking-at "\n") + (princ "\n"))))) + +;;;###autoload +(defun customize-save-customized () + "Save all user options which have been set in this session." + (interactive) + (mapatoms (lambda (symbol) + (let ((face (get symbol 'customized-face)) + (value (get symbol 'customized-value))) + (when face + (put symbol 'saved-face face) + (put symbol 'customized-face nil)) + (when value + (put symbol 'saved-value value) + (put symbol 'customized-value nil))))) + ;; We really should update all custom buffers here. + (custom-save-all)) + +;;;###autoload +(defun custom-save-all () + "Save all customizations in `custom-file'." + (let ((inhibit-read-only t)) + (custom-save-variables) + (custom-save-faces) + (let ((find-file-hooks nil) + (auto-mode-alist)) + (with-current-buffer (find-file-noselect custom-file) + (save-buffer))))) + + +;;; The Customize Menu. + +;;; Menu support + +(defun custom-face-menu-create (widget symbol) + "Ignoring WIDGET, create a menu entry for customization face SYMBOL." + (vector (custom-unlispify-menu-entry symbol) + `(customize-face ',symbol) + t)) + +(defun custom-variable-menu-create (widget symbol) + "Ignoring WIDGET, create a menu entry for customization variable SYMBOL." + (let ((type (get symbol 'custom-type))) + (unless (listp type) + (setq type (list type))) + (if (and type (widget-get type :custom-menu)) + (widget-apply type :custom-menu symbol) + (vector (custom-unlispify-menu-entry symbol) + `(customize-variable ',symbol) + t)))) + +;; Add checkboxes to boolean variable entries. +(widget-put (get 'boolean 'widget-type) + :custom-menu (lambda (widget symbol) + `[,(custom-unlispify-menu-entry symbol) + (customize-variable ',symbol) + :style toggle + :selected ,symbol])) + +;; XEmacs can create menus dynamically. +(defun custom-group-menu-create (widget symbol) + "Ignoring WIDGET, create a menu entry for customization group SYMBOL." + `( ,(custom-unlispify-menu-entry symbol t) + :filter (lambda (&rest junk) + (let ((item (custom-menu-create ',symbol))) + (if (listp item) + (cdr item) + (list item)))))) + +;;;###autoload +(defun custom-menu-create (symbol) + "Create menu for customization group SYMBOL. +The menu is in a format applicable to `easy-menu-define'." + (let* ((item (vector (custom-unlispify-menu-entry symbol) + `(customize-group ',symbol) + t))) + ;; Item is the entry for creating a menu buffer for SYMBOL. + ;; We may nest, if the menu is not too big. + (custom-load-symbol symbol) + (if (< (length (get symbol 'custom-group)) widget-menu-max-size) + ;; The menu is not too big. + (let ((custom-prefix-list (custom-prefix-add symbol + custom-prefix-list)) + (members (custom-sort-items (get symbol 'custom-group) + custom-menu-sort-alphabetically + custom-menu-order-groups))) + ;; Create the menu. + `(,(custom-unlispify-menu-entry symbol t) + ,item + "--" + ,@(mapcar (lambda (entry) + (widget-apply (if (listp (nth 1 entry)) + (nth 1 entry) + (list (nth 1 entry))) + :custom-menu (nth 0 entry))) + members))) + ;; The menu was too big. + item))) + +;;;###autoload +(defun customize-menu-create (symbol &optional name) + "Return a customize menu for customization group SYMBOL. +If optional NAME is given, use that as the name of the menu. +Otherwise the menu will be named `Customize'. +The format is suitable for use with `easy-menu-define'." + (unless name + (setq name "Customize")) + `(,name + :filter (lambda (&rest junk) + (cdr (custom-menu-create ',symbol))))) + +;;; The Custom Mode. + +(defvar custom-mode-map nil + "Keymap for `custom-mode'.") + +(unless custom-mode-map + (setq custom-mode-map (make-sparse-keymap)) + (set-keymap-parents custom-mode-map widget-keymap) + (suppress-keymap custom-mode-map) + (define-key custom-mode-map " " 'scroll-up) + (define-key custom-mode-map "\177" 'scroll-down) + (define-key custom-mode-map "q" 'bury-buffer) + (define-key custom-mode-map "u" 'Custom-goto-parent) + (define-key custom-mode-map "n" 'widget-forward) + (define-key custom-mode-map "p" 'widget-backward) + ;; (define-key custom-mode-map [mouse-1] 'Custom-move-and-invoke) + ) + +(defun Custom-move-and-invoke (event) + "Move to where you click, and if it is an active field, invoke it." + (interactive "e") + (mouse-set-point event) + (if (widget-event-point event) + (let* ((pos (widget-event-point event)) + (button (get-char-property pos 'button))) + (if button + (widget-button-click event))))) + +(easy-menu-define Custom-mode-menu + custom-mode-map + "Menu used in customization buffers." + `("Custom" + ,(customize-menu-create 'customize) + ["Set" Custom-set t] + ["Save" Custom-save t] + ["Reset to Current" Custom-reset-current t] + ["Reset to Saved" Custom-reset-saved t] + ["Reset to Standard Settings" Custom-reset-standard t] + ["Info" (Info-goto-node "(xemacs)Easy Customization") t])) + +(defun Custom-goto-parent () + "Go to the parent group listed at the top of this buffer. +If several parents are listed, go to the first of them." + (interactive) + (save-excursion + (goto-char (point-min)) + (if (search-forward "\nGo to parent group: " nil t) + (let* ((button (get-char-property (point) 'button)) + (parent (downcase (widget-get button :tag)))) + (customize-group parent))))) + +(defcustom custom-mode-hook nil + "Hook called when entering custom-mode." + :type 'hook + :group 'custom-buffer ) + +(defun custom-state-buffer-message (widget) + (if (eq (widget-get (widget-get widget :parent) :custom-state) 'modified) + (message + "To install your edits, invoke [State] and choose the Set operation"))) + +(defun custom-mode () + "Major mode for editing customization buffers. + +The following commands are available: + +Move to next button or editable field. \\[widget-forward] +Move to previous button or editable field. \\[widget-backward] +\\\ +Complete content of editable text field. \\[widget-complete] +\\\ +Invoke button under the mouse pointer. \\[Custom-move-and-invoke] +Invoke button under point. \\[widget-button-press] +Set all modifications. \\[Custom-set] +Make all modifications default. \\[Custom-save] +Reset all modified options. \\[Custom-reset-current] +Reset all modified or set options. \\[Custom-reset-saved] +Reset all options. \\[Custom-reset-standard] + +Entry to this mode calls the value of `custom-mode-hook' +if that value is non-nil." + (kill-all-local-variables) + (setq major-mode 'custom-mode + mode-name "Custom") + (use-local-map custom-mode-map) + (easy-menu-add Custom-mode-menu) + (make-local-variable 'custom-options) + (make-local-variable 'widget-documentation-face) + (setq widget-documentation-face 'custom-documentation-face) + (make-local-variable 'widget-button-face) + (setq widget-button-face 'custom-button-face) + (make-local-hook 'widget-edit-functions) + (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t) + (run-hooks 'custom-mode-hook)) + + +;;; The End. + +(provide 'cus-edit) + +;; cus-edit.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cus-face.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cus-face.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,255 @@ +;;; cus-face.el -- Support for Custom faces. +;; +;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. +;; +;; Author: Per Abrahamsen +;; Maintainer: Hrvoje Niksic +;; Keywords: help, faces +;; Version: 1.9960-x +;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ + +;;; Commentary: +;; +;; See `custom.el'. + +;; This file should probably be dissolved, and code moved to faces.el, +;; like Stallman did. + +;;; Code: + +(require 'custom) + +;; To elude the warnings for font functions. +(eval-when-compile + (require 'font)) + +;;; Declaring a face. + +;;;###autoload +(defun custom-declare-face (face spec doc &rest args) + "Like `defface', but FACE is evaluated as a normal argument." + ;; (when (fboundp 'load-gc) + ;; (error "Attempt to declare a face during dump")) + (unless (get face 'face-defface-spec) + (put face 'face-defface-spec spec) + (unless (find-face face) + ;; If the user has already created the face, respect that. + (let ((value (or (get face 'saved-face) spec)) + (frames (relevant-custom-frames)) + frame) + ;; Create global face. + (make-empty-face face) + (face-display-set face value) + ;; Create frame local faces + (while frames + (setq frame (car frames) + frames (cdr frames)) + (face-display-set face value frame)) + (init-face-from-resources face))) + (when (and doc (null (face-doc-string face))) + (set-face-doc-string face doc)) + (custom-handle-all-keywords face args 'custom-face) + (run-hooks 'custom-define-hook)) + face) + +;;; Font Attributes. + +(defconst custom-face-attributes + '((:bold (boolean :tag "Bold" + :help-echo "Control whether a bold font should be used.") + custom-set-face-bold custom-face-bold) + (:italic (boolean :tag "Italic" + :help-echo "\ +Control whether an italic font should be used.") + custom-set-face-italic custom-face-italic) + (:underline (boolean :tag "Underline" + :help-echo "\ +Control whether the text should be underlined.") + set-face-underline-p face-underline-p) + (:foreground (color :tag "Foreground" + :value "" + :help-echo "Set foreground color.") + set-face-foreground face-foreground-name) + (:background (color :tag "Background" + :value "" + :help-echo "Set background color.") + set-face-background face-background-name) + ;; #### Should make it work on X + (:inverse-video (boolean :tag "Inverse" + :help-echo "\ +Control whether the text should be inverted. Works only on TTY-s") + set-face-reverse-p face-reverse-p) + (:stipple (editable-field :format "Stipple: %v" + :help-echo "Name of background bitmap file.") + set-face-background-pixmap custom-face-stipple) + (:family (editable-field :format "Font Family: %v" + :help-echo "\ +Name of font family to use (e.g. times).") + custom-set-face-font-family custom-face-font-family) + (:size (editable-field :format "Size: %v" + :help-echo "\ +Text size (e.g. 9pt or 2mm).") + custom-set-face-font-size custom-face-font-size) + (:strikethru (toggle :format "%[Strikethru%]: %v\n" + :help-echo "\ +Control whether the text should be strikethru.") + set-face-strikethru-p face-strikethru-p)) + "Alist of face attributes. + +The elements are of the form (KEY TYPE SET GET) where KEY is a symbol +identifying the attribute, TYPE is a widget type for editing the +attibute, SET is a function for setting the attribute value, and GET is a function for getiing the attribute value. + +The SET function should take three arguments, the face to modify, the +value of the attribute, and optionally the frame where the face should +be changed. + +The GET function should take two arguments, the face to examine, and +optonally the frame where the face should be examined.") + +(defun face-custom-attributes-set (face frame &rest atts) + "For FACE on FRAME set the attributes [KEYWORD VALUE].... +Each keyword should be listed in `custom-face-attributes'. + +If FRAME is nil, set the default face." + (while atts + (let* ((name (nth 0 atts)) + (value (nth 1 atts)) + (fun (nth 2 (assq name custom-face-attributes)))) + (setq atts (cdr (cdr atts))) + (condition-case nil + (funcall fun face value frame) + (error nil))))) + +(defun face-custom-attributes-get (face frame) + "For FACE on FRAME get the attributes [KEYWORD VALUE].... +Each keyword should be listed in `custom-face-attributes'. + +If FRAME is nil, use the default face." + (condition-case nil + ;; Attempt to get `font.el' from w3. + (require 'font) + (error nil)) + (let ((atts custom-face-attributes) + att result get) + (while atts + (setq att (car atts) + atts (cdr atts) + get (nth 3 att)) + (condition-case nil + ;; This may fail if w3 doesn't exists. + (when get + (let ((answer (funcall get face frame))) + (unless (equal answer (funcall get 'default frame)) + (when (widget-apply (nth 1 att) :match answer) + (setq result (cons (nth 0 att) (cons answer result))))))) + (error nil))) + result)) + +(defun custom-set-face-bold (face value &optional frame) + "Set the bold property of FACE to VALUE." + (if value + (make-face-bold face frame) + (make-face-unbold face frame))) + +;; Really, we should get rid of these font.el dependencies... They +;; are still presenting a problem with dumping the faces (font.el is +;; too bloated for us to dump). I am thinking about hacking up +;; font-like functionality myself for the sake of this file. It will +;; probably be to-the-point and more efficient. + +(defun custom-face-bold (face &rest args) + "Return non-nil if the font of FACE is bold." + (let* ((font (apply 'face-font-name face args)) + ;; Gag + (fontobj (font-create-object font))) + (font-bold-p fontobj))) + +(defun custom-set-face-italic (face value &optional frame) + "Set the italic property of FACE to VALUE." + (if value + (make-face-italic face frame) + (make-face-unitalic face frame))) + +(defun custom-face-italic (face &rest args) + "Return non-nil if the font of FACE is italic." + (let* ((font (apply 'face-font-name face args)) + ;; Gag + (fontobj (font-create-object font))) + (font-italic-p fontobj))) + +(defun custom-face-stipple (face &rest args) + "Return the name of the stipple file used for FACE." + (let ((image (apply 'specifier-instance + (face-background-pixmap face) args))) + (and image + (image-instance-file-name image)))) + +(defun custom-set-face-font-size (face size &rest args) + "Set the font of FACE to SIZE" + (let* ((font (apply 'face-font-name face args)) + ;; Gag + (fontobj (font-create-object font))) + (set-font-size fontobj size) + (apply 'font-set-face-font face fontobj args))) + +(defun custom-face-font-size (face &rest args) + "Return the size of the font of FACE as a string." + (let* ((font (apply 'face-font-name face args)) + ;; Gag + (fontobj (font-create-object font))) + (format "%s" (font-size fontobj)))) + +(defun custom-set-face-font-family (face family &rest args) + "Set the font of FACE to FAMILY." + (let* ((font (apply 'face-font-name face args)) + ;; Gag + (fontobj (font-create-object font))) + (set-font-family fontobj family) + (apply 'font-set-face-font face fontobj args))) + +(defun custom-face-font-family (face &rest args) + "Return the name of the font family of FACE." + (let* ((font (apply 'face-font-name face args)) + ;; Gag + (fontobj (font-create-object font))) + (font-family fontobj))) + +;;; Initializing. + +;;;###autoload +(defun custom-set-faces (&rest args) + "Initialize faces according to user preferences. +The arguments should be a list where each entry has the form: + + (FACE SPEC [NOW]) + +SPEC will be stored as the saved value for FACE. If NOW is present +and non-nil, FACE will also be created according to SPEC. + +See `defface' for the format of SPEC." + (while args + (let ((entry (car args))) + (if (listp entry) + (let ((face (nth 0 entry)) + (spec (nth 1 entry)) + (now (nth 2 entry))) + (put face 'saved-face spec) + (when now + (put face 'force-face t)) + (when (or now (find-face face)) + (unless (find-face face) + (make-empty-face face)) + (face-spec-set face spec)) + (setq args (cdr args))) + ;; Old format, a plist of FACE SPEC pairs. + (let ((face (nth 0 args)) + (spec (nth 1 args))) + (put face 'saved-face spec)) + (setq args (cdr (cdr args))))))) + +;;; The End. + +(provide 'cus-face) + +;; cus-face.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cus-load.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cus-load.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,72 @@ +;;; cus-load.el --- Batch load all available cus-load files + +;; Copyright (C) 1997 by Free Software Foundation, Inc. + +;; Author: Steven L Baur +;; Keywords: internal, help, faces + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Not in FSF + +;;; Commentary: + +;; In FSF all of the custom loads are in a single `cus-load' file. +;; However, we have them distributed across directories, with optional +;; incremental loading. Here we simply collect the whole set. + + +;;; Code: + +(require 'custom) + + +(defun custom-add-loads (symbol list) + "Update the custom-loads list of a symbol. +This works by adding the elements from LIST to the SYMBOL's +`custom-loads' property, avoiding duplicates. Also, SYMBOL is +added to `custom-group-hash-table'." + (let ((loads (get symbol 'custom-loads))) + (dolist (el list) + (unless (member el loads) + (setq loads (nconc loads (list el))))) + (put symbol 'custom-loads loads) + (puthash symbol t custom-group-hash-table))) + +;; custom-add-loads was named custom-put (and accepted different +;; arguments) during the 20.3 beta cycle. Support it for +;; compatibility. +(defun custom-put (symbol ignored list) + (custom-add-loads symbol list)) +(make-obsolete 'custom-put 'custom-add-loads) + + +(message "Loading customization dependencies...") + +;; Garbage-collection seems to be very intensive here, and it slows +;; things down. Nuke it. +(let ((gc-cons-threshold 10000000)) + (mapc (lambda (dir) + (load (expand-file-name "custom-load" dir) t t)) + load-path)) + +(message "Loading customization dependencies...done") + +(provide 'cus-load) + +;;; cus-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/cus-start.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cus-start.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,205 @@ +;;; cus-start.el --- define customization properties of builtins. + +;; Copyright (C) 1997 Free Software Foundation, Inc. + +;; Author: Per Abrahamsen +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Not synched with FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; The following code is used to define the customization properties +;; for builtin variables, and variables in the packages that are +;; preloaded /very/ early, before custom.el itself (replace.el is such +;; an example). The way it handles custom stuff is dirty, and should +;; be regarded as a last resort. DO NOT add variables here, unless +;; you know what you are doing. + +;; Must be run before the user has changed the value of any options! + + +;;; Code: + +(require 'custom) + +(defun custom-start-quote (sexp) + ;; This is copied from `cus-edit.el'. + "Quote SEXP iff it is not self quoting." + (if (or (memq sexp '(t nil)) + (and (symbolp sexp) + (eq (aref (symbol-name sexp) 0) ?:)) + (and (listp sexp) + (memq (car sexp) '(lambda))) + (stringp sexp) + (numberp sexp) + (and (fboundp 'characterp) + (characterp sexp))) + sexp + (list 'quote sexp))) + +(let ((all '(;; boolean + (abbrev-all-caps abbrev boolean) + (allow-deletion-of-last-visible-frame frames boolean) + (debug-on-quit debug boolean) + (delete-auto-save-files auto-save boolean) + (delete-exited-processes processes-basics boolean) + (indent-tabs-mode editing-basics boolean) + (load-ignore-elc-files maint boolean) + (load-warn-when-source-newer maint boolean) + (load-warn-when-source-only maint boolean) + (modifier-keys-are-sticky keyboard boolean) + (no-redraw-on-reenter display boolean) + (scroll-on-clipped-lines display boolean) + (truncate-partial-width-windows display boolean) + (visible-bell sound boolean) + (x-allow-sendevents x boolean) + (zmacs-regions editing-basics boolean) + ;; integer + (auto-save-interval auto-save integer) + (bell-volume sound integer) + (echo-keystrokes keyboard integer) + (gc-cons-threshold alloc integer) + (next-screen-context-lines display integer) + (scroll-conservatively display integer) + (scroll-step windows integer) + (window-min-height windows integer) + (window-min-width windows integer) + ;; object + (auto-save-file-format auto-save + (choice (const :tag "Normal" t) + (repeat (symbol :tag "Format")))) + (completion-ignored-extensions minibuffer + (repeat + (string :format "%v"))) + (debug-ignored-errors debug (repeat (choice :format "%v" + (symbol :tag "Class") + regexp))) + (debug-on-error debug (choice (const :tag "off" nil) + (const :tag "Always" t) + (repeat :menu-tag "When" + :value (nil) + (symbol + :tag "Condition")))) + (debug-on-signal debug (choice (const :tag "off" nil) + (const :tag "Always" t) + (repeat :menu-tag "When" + :value (nil) + (symbol + :tag "Condition")))) + (exec-path processes-basics (repeat + (choice :tag "Directory" + (const :tag "Default" nil) + (directory :format "%v")))) + (file-name-handler-alist data (repeat + (cons regexp + (function :tag "Handler")))) + (shell-file-name execute file) + (stack-trace-on-error debug (choice (const :tag "off" nil) + (const :tag "Always" t) + (repeat :menu-tag "When" + :value (nil) + (symbol + :tag "Condition")))) + (stack-trace-on-signal debug (choice (const :tag "off" nil) + (const :tag "Always" t) + (repeat :menu-tag "When" + :value (nil) + (symbol + :tag "Condition")))) + ;; buffer-local + (case-fold-search matching boolean) + (ctl-arrow display (choice (integer 160) + (sexp :tag "160 (default)" + :format "%t\n"))) + (fill-column fill integer) + (left-margin fill integer) + (tab-width editing-basics integer) + (truncate-lines display boolean) + ;; not documented as user-options, but should still be + ;; customizable: + (bar-cursor display (choice (const :tag "Block Cursor" nil) + (const :tag "Bar Cursor (1 pixel)" t) + (sexp :tag "Bar Cursor (2 pixels)" + :format "%t\n" 'other))) + (default-frame-plist frames (repeat + (list :inline t + :format "%v" + (symbol :tag "Parameter") + (sexp :tag "Value")))) + (disable-auto-save-when-buffer-shrinks auto-save boolean) + (find-file-use-truenames find-file boolean) + (find-file-compare-truenames find-file boolean) + (focus-follows-mouse x boolean) + (help-char keyboard (choice character + (sexp :tag "Single key specifier"))) + (max-lisp-eval-depth limits integer) + (max-specpdl-size limits integer) + (meta-prefix-char keyboard character) + (parse-sexp-ignore-comments editing-basics boolean) + (selective-display display + (choice (const :tag "off" nil) + (integer :tag "space" + :format "%v" + 1) + (const :tag "on" t))) + (selective-display-ellipses display boolean) + (signal-error-on-buffer-boundary internal boolean) + (temp-buffer-show-function + windows (radio (function-item :tag "Temp Buffers Always in Same Frame" + :format "%t\n" + show-temp-buffer-in-current-frame) + (const :tag "Temp Buffers Like Other Buffers" nil) + (function :tag "Other"))) + (undo-threshold undo integer) + (undo-high-threshold undo integer) + (words-include-escapes editing-basics boolean) + ;; These are from replace.el, which is loaded too early + ;; to be customizable. + (case-replace matching boolean) + (query-replace-highlight matching boolean) + (list-matching-lines-default-context-lines matching integer))) + this symbol group type) + (while all + (setq this (car all) + all (cdr all) + symbol (nth 0 this) + group (nth 1 this) + type (nth 2 this)) + (if (not (boundp symbol)) + ;; This is loaded so early, there is no message + (if (fboundp 'message) + ;; If variables are removed from C code, give an error here! + (message "Intrinsic `%S' not bound" symbol)) + ;; This is called before any user can have changed the value. + (put symbol 'standard-value + (list (custom-start-quote (default-value symbol)))) + ;; Add it to the right group. + (custom-add-to-group group symbol 'custom-variable) + ;; Set the type. + (put symbol 'custom-type type)))) + +;; This is to prevent it from being reloaded by `cus-load.el'. +(provide 'cus-start) + +;;; cus-start.el ends here. diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom-load.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/custom-load.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,41 @@ +;;; custom-load.el --- automatically extracted custom dependencies + + +;;; Code: + +(custom-add-loads 'extensions '("wid-edit")) +(custom-add-loads 'custom-buffer '("cus-edit")) +(custom-add-loads 'custom-faces '("cus-edit")) +(custom-add-loads 'widgets '("wid-browse" "wid-edit")) +(custom-add-loads 'menu '("x-menubar")) +(custom-add-loads 'environment '("cus-edit" "x-toolbar")) +(custom-add-loads 'custom-menu '("cus-edit")) +(custom-add-loads 'internal '("cus-edit")) +(custom-add-loads 'buffers-menu '("x-menubar")) +(custom-add-loads 'hypermedia '("wid-edit")) +(custom-add-loads 'applications '("cus-edit")) +(custom-add-loads 'help '("cus-edit")) +(custom-add-loads 'widget-browse '("wid-browse")) +(custom-add-loads 'widget-documentation '("wid-edit")) +(custom-add-loads 'customize '("cus-edit" "wid-edit")) +(custom-add-loads 'custom-browse '("cus-edit")) +(custom-add-loads 'abbrev '("cus-edit")) +(custom-add-loads 'programming '("cus-edit")) +(custom-add-loads 'toolbar '("x-toolbar")) +(custom-add-loads 'widget-button '("wid-edit")) +(custom-add-loads 'files '("cus-edit")) +(custom-add-loads 'external '("cus-edit")) +(custom-add-loads 'development '("cus-edit")) +(custom-add-loads 'widget-faces '("wid-edit")) +(custom-add-loads 'languages '("cus-edit")) +(custom-add-loads 'custom-magic-faces '("cus-edit")) +(custom-add-loads 'faces '("cus-edit" "wid-edit")) +(custom-add-loads 'emacs '("cus-edit")) +(custom-add-loads 'processes '("cus-edit")) +(custom-add-loads 'wp '("cus-edit")) +(custom-add-loads 'editing '("cus-edit")) +(custom-add-loads 'i18n '("cus-edit")) +(custom-add-loads 'info '("x-toolbar")) +(custom-add-loads 'x '("x-faces" "x-font-menu")) + +;;; custom-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/custom.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,398 @@ +;;; custom.el -- Tools for declaring and initializing options. + +;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. + +;; Author: Per Abrahamsen +;; Maintainer: Hrvoje Niksic +;; Keywords: help, faces, dumped +;; Version: 1.9960-x +;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; This file only contain the code needed to declare and initialize +;; user options. The code to customize options is autoloaded from +;; `cus-edit.el'. +;; +;; The code implementing face declarations is in `cus-face.el' + +;;; Code: + +(require 'widget) + +(defvar custom-define-hook nil + ;; Customize information for this option is in `cus-edit.el'. + "Hook called after defining each customize option.") + +;;; The `defcustom' Macro. + +(defun custom-initialize-default (symbol value) + "Initialize SYMBOL with VALUE. +This will do nothing if symbol already has a default binding. +Otherwise, if symbol has a `saved-value' property, it will evaluate +the car of that and used as the default binding for symbol. +Otherwise, VALUE will be evaluated and used as the default binding for +symbol." + (unless (default-boundp symbol) + ;; Use the saved value if it exists, otherwise the standard setting. + (set-default symbol (if (get symbol 'saved-value) + (eval (car (get symbol 'saved-value))) + (eval value))))) + +(defun custom-initialize-set (symbol value) + "Initialize SYMBOL with VALUE. +Like `custom-initialize-default', but use the function specified by +`:set' to initialize SYMBOL." + (unless (default-boundp symbol) + (funcall (or (get symbol 'custom-set) 'set-default) + symbol + (if (get symbol 'saved-value) + (eval (car (get symbol 'saved-value))) + (eval value))))) + +(defun custom-initialize-reset (symbol value) + "Initialize SYMBOL with VALUE. +Like `custom-initialize-set', but use the function specified by +`:get' to reinitialize SYMBOL if it is already bound." + (funcall (or (get symbol 'custom-set) 'set-default) + symbol + (cond ((default-boundp symbol) + (funcall (or (get symbol 'custom-get) 'default-value) + symbol)) + ((get symbol 'saved-value) + (eval (car (get symbol 'saved-value)))) + (t + (eval value))))) + +(defun custom-initialize-changed (symbol value) + "Initialize SYMBOL with VALUE. +Like `custom-initialize-reset', but only use the `:set' function if the +not using the standard setting. Otherwise, use the `set-default'." + (cond ((default-boundp symbol) + (funcall (or (get symbol 'custom-set) 'set-default) + symbol + (funcall (or (get symbol 'custom-get) 'default-value) + symbol))) + ((get symbol 'saved-value) + (funcall (or (get symbol 'custom-set) 'set-default) + symbol + (eval (car (get symbol 'saved-value))))) + (t + (set-default symbol (eval value))))) + +(defun custom-declare-variable (symbol value doc &rest args) + "Like `defcustom', but SYMBOL and VALUE are evaluated as normal arguments." + ;; Remember the standard setting. + (put symbol 'standard-value (list value)) + ;; Maybe this option was rogue in an earlier version. It no longer is. + (when (get symbol 'force-value) + ;; It no longer is. + (put symbol 'force-value nil)) + (when doc + (put symbol 'variable-documentation doc)) + (let ((initialize 'custom-initialize-reset) + (requests nil)) + (while args + (let ((arg (car args))) + (setq args (cdr args)) + (unless (symbolp arg) + (error "Junk in args %S" args)) + (let ((keyword arg) + (value (car args))) + (unless args + (error "Keyword %s is missing an argument" keyword)) + (setq args (cdr args)) + (cond ((eq keyword :initialize) + (setq initialize value)) + ((eq keyword :set) + (put symbol 'custom-set value)) + ((eq keyword :get) + (put symbol 'custom-get value)) + ((eq keyword :require) + (setq requests (cons value requests))) + ((eq keyword :type) + (put symbol 'custom-type value)) + ((eq keyword :options) + (if (get symbol 'custom-options) + ;; Slow safe code to avoid duplicates. + (mapc (lambda (option) + (custom-add-option symbol option)) + value) + ;; Fast code for the common case. + (put symbol 'custom-options (copy-sequence value)))) + (t + (custom-handle-keyword symbol keyword value + 'custom-variable)))))) + (put symbol 'custom-requests requests) + ;; Do the actual initialization. + (funcall initialize symbol value)) + (run-hooks 'custom-define-hook) + symbol) + +(defmacro defcustom (symbol value doc &rest args) + "Declare SYMBOL as a customizable variable that defaults to VALUE. +DOC is the variable documentation. + +Neither SYMBOL nor VALUE needs to be quoted. +If SYMBOL is not already bound, initialize it to VALUE. +The remaining arguments should have the form + + [KEYWORD VALUE]... + +The following KEYWORD's are defined: + +:type VALUE should be a widget type for editing the symbols value. + The default is `sexp'. +:options VALUE should be a list of valid members of the widget type. +:group VALUE should be a customization group. + Add SYMBOL to that group. +:initialize VALUE should be a function used to initialize the + variable. It takes two arguments, the symbol and value + given in the `defcustom' call. The default is + `custom-initialize-set' +:set VALUE should be a function to set the value of the symbol. + It takes two arguments, the symbol to set and the value to + give it. The default is `set-default'. +:get VALUE should be a function to extract the value of symbol. + The function takes one argument, a symbol, and should return + the current value for that symbol. The default is + `default-value'. +:require VALUE should be a feature symbol. Each feature will be + required after initialization, of the the user have saved this + option. + +Read the section about customization in the Emacs Lisp manual for more +information." + `(custom-declare-variable (quote ,symbol) (quote ,value) ,doc ,@args)) + +;;; The `defface' Macro. + +(defmacro defface (face spec doc &rest args) + "Declare FACE as a customizable face that defaults to SPEC. +FACE does not need to be quoted. + +Third argument DOC is the face documentation. + +If FACE has been set with `custom-set-face', set the face attributes +as specified by that function, otherwise set the face attributes +according to SPEC. + +The remaining arguments should have the form + + [KEYWORD VALUE]... + +The following KEYWORDs are defined: + +:group VALUE should be a customization group. + Add FACE to that group. + +SPEC should be an alist of the form ((DISPLAY ATTS)...). + +ATTS is a list of face attributes and their values. The possible +attributes are defined in the variable `custom-face-attributes'. + +The ATTS of the first entry in SPEC where the DISPLAY matches the +frame should take effect in that frame. DISPLAY can either be the +symbol t, which will match all frames, or an alist of the form +\((REQ ITEM...)...) + +For the DISPLAY to match a FRAME, the REQ property of the frame must +match one of the ITEM. The following REQ are defined: + +`type' (the value of `window-system') + Should be one of `x' or `tty'. + +`class' (the frame's color support) + Should be one of `color', `grayscale', or `mono'. + +`background' (what color is used for the background text) + Should be one of `light' or `dark'. + +Read the section about customization in the Emacs Lisp manual for more +information." + `(custom-declare-face (quote ,face) ,spec ,doc ,@args)) + +;;; The `defgroup' Macro. + +(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)) + (pop members)) + (put symbol 'custom-group (nconc members (get symbol 'custom-group))) + (when doc + (put symbol 'group-documentation doc)) + (while args + (let ((arg (car args))) + (setq args (cdr args)) + (unless (symbolp arg) + (error "Junk in args %S" args)) + (let ((keyword arg) + (value (car args))) + (unless args + (error "Keyword %s is missing an argument" keyword)) + (setq args (cdr args)) + (cond ((eq keyword :prefix) + (put symbol 'custom-prefix value)) + (t + (custom-handle-keyword symbol keyword value + 'custom-group)))))) + (run-hooks 'custom-define-hook) + symbol) + +(defmacro defgroup (symbol members doc &rest args) + "Declare SYMBOL as a customization group containing MEMBERS. +SYMBOL does not need to be quoted. + +Third arg DOC is the group documentation. + +MEMBERS should be an alist of the form ((NAME WIDGET)...) where NAME +is a symbol and WIDGET is a widget for editing that symbol. Useful +widgets are `custom-variable' for editing variables, `custom-face' for +edit faces, and `custom-group' for editing groups. + +The remaining arguments should have the form + + [KEYWORD VALUE]... + +The following KEYWORD's are defined: + +:group VALUE should be a customization group. + Add SYMBOL to that group. + +Read the section about customization in the Emacs Lisp manual for more +information." + `(custom-declare-group (quote ,symbol) ,members ,doc ,@args)) + +;; This is preloaded very early, so we avoid using CL features. +(defvar custom-group-hash-table (make-hashtable 300 'eq) + "Hash-table of non-empty groups.") + +(defun custom-add-to-group (group option widget) + "To existing GROUP add a new OPTION of type WIDGET. +If there already is an entry for that option, overwrite it." + (let* ((members (get group 'custom-group)) + (old (assq option members))) + (if old + (setcar (cdr old) widget) + (put group 'custom-group (nconc members (list (list option widget)))))) + (puthash group t custom-group-hash-table)) + +;;; Properties. + +(defun custom-handle-all-keywords (symbol args type) + "For customization option SYMBOL, handle keyword arguments ARGS. +Third argument TYPE is the custom option type." + (while args + (let ((arg (car args))) + (setq args (cdr args)) + (unless (symbolp arg) + (error "Junk in args %S" args)) + (let ((keyword arg) + (value (car args))) + (unless args + (error "Keyword %s is missing an argument" keyword)) + (setq args (cdr args)) + (custom-handle-keyword symbol keyword value type))))) + +(defun custom-handle-keyword (symbol keyword value type) + "For customization option SYMBOL, handle KEYWORD with VALUE. +Fourth argument TYPE is the custom option type." + (cond ((eq keyword :group) + (custom-add-to-group value symbol type)) + ((eq keyword :link) + (custom-add-link symbol value)) + ((eq keyword :load) + (custom-add-load symbol value)) + ((eq keyword :tag) + (put symbol 'custom-tag value)) + (t + (error "Unknown keyword %s" symbol)))) + +(defun custom-add-option (symbol option) + "To the variable SYMBOL add OPTION. + +If SYMBOL is a hook variable, OPTION should be a hook member. +For other types variables, the effect is undefined." + (let ((options (get symbol 'custom-options))) + (unless (member option options) + (put symbol 'custom-options (cons option options))))) + +(defun custom-add-link (symbol widget) + "To the custom option SYMBOL add the link WIDGET." + (let ((links (get symbol 'custom-links))) + (unless (member widget links) + (put symbol 'custom-links (cons widget links))))) + +(defun custom-add-load (symbol load) + "To the custom option SYMBOL add the dependency LOAD. +LOAD should be either a library file name, or a feature name." + (let ((loads (get symbol 'custom-loads))) + (unless (member load loads) + (put symbol 'custom-loads (cons load loads))))) + +;;; Initializing. + +(defun custom-set-variables (&rest args) + "Initialize variables according to user preferences. + +The arguments should be a list where each entry has the form: + + (SYMBOL VALUE [NOW]) + +The unevaluated VALUE is stored as the saved value for SYMBOL. +If NOW is present and non-nil, VALUE is also evaluated and bound as +the default value for the SYMBOL." + (while args + (let ((entry (car args))) + (if (listp entry) + (let* ((symbol (nth 0 entry)) + (value (nth 1 entry)) + (now (nth 2 entry)) + (requests (nth 3 entry)) + (set (or (get symbol 'custom-set) 'set-default))) + (put symbol 'saved-value (list value)) + (cond (now + ;; Rogue variable, set it now. + (put symbol 'force-value t) + (funcall set symbol (eval value))) + ((default-boundp symbol) + ;; Something already set this, overwrite it. + (funcall set symbol (eval value)))) + (when requests + (put symbol 'custom-requests requests) + (mapc 'require requests)) + (setq args (cdr args))) + ;; Old format, a plist of SYMBOL VALUE pairs. + (message "Warning: old format `custom-set-variables'") + (ding) + (sit-for 2) + (let ((symbol (nth 0 args)) + (value (nth 1 args))) + (put symbol 'saved-value (list value))) + (setq args (cdr (cdr args))))))) + +;;; The End. + +(provide 'custom) + +;; custom.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/auto-autoloads.el --- a/lisp/custom/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,197 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'custom-autoloads) (error "Already loaded")) - -;;;### (autoloads (Custom-make-dependencies) "cus-dep" "custom/cus-dep.el") - -(autoload 'Custom-make-dependencies "cus-dep" "\ -Extract custom dependencies from .el files in SUBDIRS. -SUBDIRS is a list of directories. If it is nil, the command-line -arguments are used. If it is a string, only that directory is -processed. This function is especially useful in batch mode. - -Batch usage: xemacs -batch -l cus-dep.el -f Custom-make-dependencies DIRS" t nil) - -;;;*** - -;;;### (autoloads (customize-menu-create custom-menu-create custom-save-all customize-save-customized customize-browse custom-buffer-create-other-window custom-buffer-create customize-apropos-groups customize-apropos-faces customize-apropos-options customize-apropos customize-saved customize-customized customize-face-other-window customize-face customize-option-other-window customize-variable customize-other-window customize customize-save-variable customize-set-variable customize-set-value) "cus-edit" "custom/cus-edit.el") - -(autoload 'customize-set-value "cus-edit" "\ -Set VARIABLE to VALUE. VALUE is a Lisp object. - -If VARIABLE has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If VARIABLE has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value." t nil) - -(autoload 'customize-set-variable "cus-edit" "\ -Set the default for VARIABLE to VALUE. VALUE is a Lisp object. - -If VARIABLE has a `custom-set' property, that is used for setting -VARIABLE, otherwise `set-default' is used. - -The `customized-value' property of the VARIABLE will be set to a list -with a quoted VALUE as its sole list member. - -If VARIABLE has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If VARIABLE has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value. " t nil) - -(autoload 'customize-save-variable "cus-edit" "\ -Set the default for VARIABLE to VALUE, and save it for future sessions. -If VARIABLE has a `custom-set' property, that is used for setting -VARIABLE, otherwise `set-default' is used. - -The `customized-value' property of the VARIABLE will be set to a list -with a quoted VALUE as its sole list member. - -If VARIABLE has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If VARIABLE has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value. " t nil) - -(autoload 'customize "cus-edit" "\ -Select a customization buffer which you can use to set user options. -User options are structured into \"groups\". -The default group is `Emacs'." t nil) - -(defalias 'customize-group 'customize) - -(autoload 'customize-other-window "cus-edit" "\ -Customize SYMBOL, which must be a customization group." t nil) - -(defalias 'customize-group-other-window 'customize-other-window) - -(defalias 'customize-option 'customize-variable) - -(autoload 'customize-variable "cus-edit" "\ -Customize SYMBOL, which must be a user option variable." t nil) - -(defalias 'customize-variable-other-window 'customize-option-other-window) - -(autoload 'customize-option-other-window "cus-edit" "\ -Customize SYMBOL, which must be a user option variable. -Show the buffer in another window, but don't select it." t nil) - -(autoload 'customize-face "cus-edit" "\ -Customize SYMBOL, which should be a face name or nil. -If SYMBOL is nil, customize all faces." t nil) - -(autoload 'customize-face-other-window "cus-edit" "\ -Show customization buffer for FACE in other window." t nil) - -(autoload 'customize-customized "cus-edit" "\ -Customize all user options set since the last save in this session." t nil) - -(autoload 'customize-saved "cus-edit" "\ -Customize all already saved user options." t nil) - -(autoload 'customize-apropos "cus-edit" "\ -Customize all user options matching REGEXP. -If ALL is `options', include only options. -If ALL is `faces', include only faces. -If ALL is `groups', include only groups. -If ALL is t (interactively, with prefix arg), include options which are not -user-settable, as well as faces and groups." t nil) - -(autoload 'customize-apropos-options "cus-edit" "\ -Customize all user options matching REGEXP. -With prefix arg, include options which are not user-settable." t nil) - -(autoload 'customize-apropos-faces "cus-edit" "\ -Customize all user faces matching REGEXP." t nil) - -(autoload 'customize-apropos-groups "cus-edit" "\ -Customize all user groups matching REGEXP." t nil) - -(autoload 'custom-buffer-create "cus-edit" "\ -Create a buffer containing OPTIONS. -Optional NAME is the name of the buffer. -OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where -SYMBOL is a customization option, and WIDGET is a widget for editing -that option." nil nil) - -(autoload 'custom-buffer-create-other-window "cus-edit" "\ -Create a buffer containing OPTIONS. -Optional NAME is the name of the buffer. -OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where -SYMBOL is a customization option, and WIDGET is a widget for editing -that option." nil nil) - -(autoload 'customize-browse "cus-edit" "\ -Create a tree browser for the customize hierarchy." t nil) - -(defcustom custom-file (if (boundp 'emacs-user-extension-dir) (concat "~" init-file-user emacs-user-extension-dir "options.el") "~/.emacs") "File used for storing customization information.\nIf you change this from the default \"~/.emacs\" you need to\nexplicitly load that file for the settings to take effect." :type 'file :group 'customize) - -(autoload 'customize-save-customized "cus-edit" "\ -Save all user options which have been set in this session." t nil) - -(autoload 'custom-save-all "cus-edit" "\ -Save all customizations in `custom-file'." nil nil) - -(autoload 'custom-menu-create "cus-edit" "\ -Create menu for customization group SYMBOL. -The menu is in a format applicable to `easy-menu-define'." nil nil) - -(autoload 'customize-menu-create "cus-edit" "\ -Return a customize menu for customization group SYMBOL. -If optional NAME is given, use that as the name of the menu. -Otherwise the menu will be named `Customize'. -The format is suitable for use with `easy-menu-define'." nil nil) - -;;;*** - -;;;### (autoloads (custom-set-faces custom-declare-face) "cus-face" "custom/cus-face.el") - -(autoload 'custom-declare-face "cus-face" "\ -Like `defface', but FACE is evaluated as a normal argument." nil nil) - -(autoload 'custom-set-faces "cus-face" "\ -Initialize faces according to user preferences. -The arguments should be a list where each entry has the form: - - (FACE SPEC [NOW]) - -SPEC will be stored as the saved value for FACE. If NOW is present -and non-nil, FACE will also be created according to SPEC. - -See `defface' for the format of SPEC." nil nil) - -;;;*** - -;;;### (autoloads (widget-minor-mode widget-browse-other-window widget-browse widget-browse-at) "wid-browse" "custom/wid-browse.el") - -(autoload 'widget-browse-at "wid-browse" "\ -Browse the widget under point." t nil) - -(autoload 'widget-browse "wid-browse" "\ -Create a widget browser for WIDGET." t nil) - -(autoload 'widget-browse-other-window "wid-browse" "\ -Show widget browser for WIDGET in other window." t nil) - -(autoload 'widget-minor-mode "wid-browse" "\ -Togle minor mode for traversing widgets. -With arg, turn widget mode on if and only if arg is positive." t nil) - -;;;*** - -;;;### (autoloads (widget-delete widget-create widget-prompt-value) "wid-edit" "custom/wid-edit.el") - -(autoload 'widget-prompt-value "wid-edit" "\ -Prompt for a value matching WIDGET, using PROMPT. -The current value is assumed to be VALUE, unless UNBOUND is non-nil." nil nil) - -(autoload 'widget-create "wid-edit" "\ -Create widget of TYPE. -The optional ARGS are additional keyword arguments." nil nil) - -(autoload 'widget-delete "wid-edit" "\ -Delete WIDGET." nil nil) - -;;;*** - -(provide 'custom-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/cus-dep.el --- a/lisp/custom/cus-dep.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -;;; cus-dep.el --- Find customization dependencies. -;; -;; Copyright (C) 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen , then -;; Richar Stallman , then -;; Hrvoje Niksic (rewritten for XEmacs) -;; Maintainer: Hrvoje Niksic -;; Keywords: internal - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Synched up with: Not synched with FSF. - - -;;; Commentary: - -;; This file generates the custom-load files, loaded by cus-load.el. -;; The only entry point is `Custom-make-dependencies'. - -;; It works by scanning all the `.el' files in a directory, and -;; evaluates any `defcustom', `defgroup', or `defface' expression that -;; it finds. The symbol changed by this expression is stored to a -;; hash table as the hash key, file name being the value. - -;; After all the files have been examined, custom-loads.el is -;; generated by mapping all the atoms, and seeing if any of them -;; contains a `custom-group' property. This property is a list whose -;; each element's car is the "child" group symbol. If that property -;; is in the hash-table, the file name will be looked up from the -;; hash-table, and added to cusload-file. Because the hash-table is -;; cleared whenever we process a new directory, we cannot get confused -;; by custom-loads from another directory, or from a previous -;; installation. This is also why it is perfectly safe to have old -;; custom-loads around, and have them loaded by `cus-load.el' (as -;; invoked by `cus-edit.el'). - -;; A trivial, but useful optimization is that if cusload-file exists, -;; and no .el files in the directory are newer than cusload-file, it -;; will not be generated. This means that the directories where -;; nothing has changed will be skipped. - -;; The `custom-put' function, used by files generated by -;; `Custom-make-dependencies', is a specialized function that updates -;; a property (which must be a list of strings) with a new list of -;; strings, eliminating the duplicates. As it also adds an -;; appropriate entry to a custom hash-table, *do not* use it outside -;; of custom. Its inner workings can change anytime, without prior -;; notice. `custom-put' is defined in `cus-load.el'. - -;; Example: - -;; (custom-put 'foo 'custom-loads '("bar" "baz")) -;; (get 'foo 'custom-loads) -;; => ("bar" "baz") -;; -;; (custom-put 'foo 'custom-loads '("hmph" "baz" "quz")) -;; (get 'foo 'custom-loads) -;; => ("bar" "baz" "hmph" "qux") - -;; Obviously, this allows correct incremental loading of custom-load -;; files. This is not necessary under FSF (they use a simple `put'), -;; since they have only *one* file. With the advent of packages, we -;; cannot afford the same luxury. - - -;;; Code: - -(require 'cl) -(require 'widget) -(require 'cus-face) - -;; Don't change this, unless you plan to change the code in -;; cus-start.el, too. -(defconst cusload-base-file "custom-load.el") - -;; Be very careful when changing this function. It looks easy to -;; understand, but is in fact very easy to break. Be sure to read and -;; understand the commentary above! - -;;;###autoload -(defun Custom-make-dependencies (&optional subdirs) - "Extract custom dependencies from .el files in SUBDIRS. -SUBDIRS is a list of directories. If it is nil, the command-line -arguments are used. If it is a string, only that directory is -processed. This function is especially useful in batch mode. - -Batch usage: xemacs -batch -l cus-dep.el -f Custom-make-dependencies DIRS" - (interactive "DDirectory: ") - (and (stringp subdirs) - (setq subdirs (list subdirs))) - (or subdirs - ;; Usurp the command-line-args - (setq subdirs command-line-args-left - command-line-args-left nil)) - (setq subdirs (mapcar #'expand-file-name subdirs)) - (with-temp-buffer - (let ((enable-local-eval nil) - (hash (make-hash-table :test 'eq))) - (dolist (dir subdirs) - (princ (format "Processing %s\n" dir)) - (let ((cusload-file (expand-file-name cusload-base-file dir)) - (files (directory-files dir t "\\`[^=].*\\.el\\'"))) - ;; A trivial optimization: if no file in the directory is - ;; newer than custom-load.el, no need to do anything! - (if (and (file-exists-p cusload-file) - (dolist (file files t) - (when (file-newer-than-file-p file cusload-file) - (return nil)))) - (princ "(No changes need to be written)\n") - ;; Process directory - (dolist (file files) - (when (file-exists-p file) - (erase-buffer) - (insert-file-contents file) - (goto-char (point-min)) - (let ((name (file-name-sans-extension - (file-name-nondirectory file)))) - ;; Search for defcustom/defface/defgroup - ;; expressions, and evaluate them. - (ignore-errors - (while (re-search-forward - "^(defcustom\\|^(defface\\|^(defgroup" - nil t) - (beginning-of-line) - (let ((expr (read (current-buffer)))) - (eval expr) - ;; Hash the file of the affected symbol. - (setf (gethash (nth 1 expr) hash) name))))))) - (cond - ((zerop (hash-table-count hash)) - (princ "(No customization dependencies") - (when (file-exists-p cusload-file) - (princ (format ", deleting %s" cusload-file)) - (delete-file cusload-file)) - (princ ")\n")) - (t - (princ (format "Generating %s...\n" cusload-base-file)) - (with-temp-file cusload-file - (insert ";;; " cusload-base-file - " --- automatically extracted custom dependencies\n" - "\n\n;;; Code:\n\n") - (mapatoms - (lambda (sym) - (let ((members (get sym 'custom-group)) - item where found) - (when members - (while members - (setq item (car (car members)) - members (cdr members) - where (gethash item hash)) - (unless (or (null where) - (member where found)) - (if found - (insert " ") - (insert "(custom-add-loads '" - (symbol-name sym) " '(")) - (prin1 where (current-buffer)) - (push where found))) - (when found - (insert "))\n")))))) - (insert "\n;;; custom-load.el ends here\n")) - (clrhash hash))))))))) - -(provide 'cus-dep) - -;;; cus-dep.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/cus-edit.el --- a/lisp/custom/cus-edit.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3234 +0,0 @@ -;;; cus-edit.el --- Tools for customizating Emacs and Lisp packages. -;; -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Maintainer: Hrvoje Niksic -;; Keywords: help, faces -;; Version: 1.9960-x -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; This file implements the code to create and edit customize buffers. -;; -;; See `custom.el'. - -;; No commands should have names starting with `custom-' because -;; that interferes with completion. Use `customize-' for commands -;; that the user will run with M-x, and `Custom-' for interactive commands. - - -;;; Code: - -(require 'cus-face) -(require 'wid-edit) -(require 'easymenu) - -(require 'cus-load) -(require 'cus-start) - -;; Huh? This looks dirty! -(put 'custom-define-hook 'custom-type 'hook) -(put 'custom-define-hook 'standard-value '(nil)) -(custom-add-to-group 'customize 'custom-define-hook 'custom-variable) - -;;; Customization Groups. - -(defgroup emacs nil - "Customization of the One True Editor." - :link '(custom-manual "(XEmacs)Top")) - -;; Most of these groups are stolen from `finder.el', -(defgroup editing nil - "Basic text editing facilities." - :group 'emacs) - -(defgroup abbrev nil - "Abbreviation handling, typing shortcuts, macros." - :tag "Abbreviations" - :group 'editing) - -(defgroup matching nil - "Various sorts of searching and matching." - :group 'editing) - -(defgroup emulations nil - "Emulations of other editors." - :group 'editing) - -(defgroup mouse nil - "Mouse support." - :group 'editing) - -(defgroup outlines nil - "Support for hierarchical outlining." - :group 'editing) - -(defgroup external nil - "Interfacing to external utilities." - :group 'emacs) - -(defgroup bib nil - "Code related to the `bib' bibliography processor." - :tag "Bibliography" - :group 'external) - -(defgroup processes nil - "Process, subshell, compilation, and job control support." - :group 'external - :group 'development) - -(defgroup programming nil - "Support for programming in other languages." - :group 'emacs) - -(defgroup languages nil - "Specialized modes for editing programming languages." - :group 'programming) - -(defgroup lisp nil - "Lisp support, including Emacs Lisp." - :group 'languages - :group 'development) - -(defgroup c nil - "Support for the C language and related languages." - :group 'languages) - -(defgroup tools nil - "Programming tools." - :group 'programming) - -(defgroup oop nil - "Support for object-oriented programming." - :group 'programming) - -(defgroup applications nil - "Applications written in Emacs." - :group 'emacs) - -(defgroup calendar nil - "Calendar and time management support." - :group 'applications) - -(defgroup mail nil - "Modes for electronic-mail handling." - :group 'applications) - -(defgroup news nil - "Support for netnews reading and posting." - :group 'applications) - -(defgroup games nil - "Games, jokes and amusements." - :group 'applications) - -(defgroup development nil - "Support for further development of Emacs." - :group 'emacs) - -(defgroup docs nil - "Support for Emacs documentation." - :group 'development) - -(defgroup extensions nil - "Emacs Lisp language extensions." - :group 'development) - -(defgroup internal nil - "Code for Emacs internals, build process, defaults." - :group 'development) - -(defgroup maint nil - "Maintenance aids for the Emacs development group." - :tag "Maintenance" - :group 'development) - -(defgroup environment nil - "Fitting Emacs with its environment." - :group 'emacs) - -(defgroup comm nil - "Communications, networking, remote access to files." - :tag "Communication" - :group 'environment) - -(defgroup hardware nil - "Support for interfacing with exotic hardware." - :group 'environment) - -(defgroup terminals nil - "Support for terminal types." - :group 'environment) - -(defgroup unix nil - "Front-ends/assistants for, or emulators of, UNIX features." - :group 'environment) - -(defgroup vms nil - "Support code for vms." - :group 'environment) - -(defgroup i18n nil - "Internationalization and alternate character-set support." - :group 'environment - :group 'editing) - -(defgroup x nil - "The X Window system." - :group 'environment) - -(defgroup frames nil - "Support for Emacs frames and window systems." - :group 'environment) - -(defgroup data nil - "Support editing files of data." - :group 'emacs) - -(defgroup files nil - "Support editing files." - :group 'emacs) - -(defgroup wp nil - "Word processing." - :group 'emacs) - -(defgroup tex nil - "Code related to the TeX formatter." - :group 'wp) - -(defgroup faces nil - "Support for multiple fonts." - :group 'emacs) - -(defgroup hypermedia nil - "Support for links between text or other media types." - :group 'emacs) - -(defgroup help nil - "Support for on-line help systems." - :group 'emacs) - -(defgroup local nil - "Code local to your site." - :group 'emacs) - -(defgroup customize '((widgets custom-group)) - "Customization of the Customization support." - :link '(custom-manual "(custom)Top") - :link '(url-link :tag "Development Page" - "http://www.dina.kvl.dk/~abraham/custom/") - :prefix "custom-" - :group 'help) - -(defgroup custom-faces nil - "Faces used by customize." - :group 'customize - :group 'faces) - -(defgroup custom-browse nil - "Control customize browser." - :prefix "custom-" - :group 'customize) - -(defgroup custom-buffer nil - "Control customize buffers." - :prefix "custom-" - :group 'customize) - -(defgroup custom-menu nil - "Control customize menus." - :prefix "custom-" - :group 'customize) - -(defgroup abbrev-mode nil - "Word abbreviations mode." - :group 'abbrev) - -(defgroup alloc nil - "Storage allocation and gc for GNU Emacs Lisp interpreter." - :tag "Storage Allocation" - :group 'internal) - -(defgroup undo nil - "Undoing changes in buffers." - :group 'editing) - -(defgroup modeline nil - "Content of the modeline." - :group 'environment) - -(defgroup fill nil - "Indenting and filling text." - :group 'editing) - -(defgroup editing-basics nil - "Most basic editing facilities." - :group 'editing) - -(defgroup display nil - "How characters are displayed in buffers." - :group 'environment) - -(defgroup execute nil - "Executing external commands." - :group 'processes) - -(defgroup installation nil - "The Emacs installation." - :group 'environment) - -(defgroup dired nil - "Directory editing." - :group 'environment) - -(defgroup limits nil - "Internal Emacs limits." - :group 'internal) - -(defgroup debug nil - "Debugging Emacs itself." - :group 'development) - -(defgroup minibuffer nil - "Controling the behaviour of the minibuffer." - :group 'environment) - -(defgroup keyboard nil - "Input from the keyboard." - :group 'environment) - -(defgroup mouse nil - "Input from the mouse." - :group 'environment) - -(defgroup menu nil - "Input from the menus." - :group 'environment) - -(defgroup auto-save nil - "Preventing accidential loss of data." - :group 'files) - -(defgroup processes-basics nil - "Basic stuff dealing with processes." - :group 'processes) - -(defgroup mule nil - "MULE Emacs internationalization." - :group 'i18n) - -(defgroup windows nil - "Windows within a frame." - :group 'environment) - - -;;; Utilities. - -(defun custom-quote (sexp) - "Quote SEXP iff it is not self quoting." - (if (or (memq sexp '(t nil)) - (keywordp sexp) - (eq (car-safe sexp) 'lambda) - (stringp sexp) - (numberp sexp) - (characterp sexp)) - sexp - (list 'quote sexp))) - -(defun custom-split-regexp-maybe (regexp) - "If REGEXP is a string, split it to a list at `\\|'. -You can get the original back with from the result with: - (mapconcat 'identity result \"\\|\") - -IF REGEXP is not a string, return it unchanged." - (if (stringp regexp) - (split-string regexp "\\\\|") - regexp)) - -(defun custom-variable-prompt () - ;; Code stolen from `help.el'. - "Prompt for a variable, defaulting to the variable at point. -Return a list suitable for use in `interactive'." - (let ((v (variable-at-point)) - (enable-recursive-minibuffers t) - val) - (setq val (completing-read - (if (symbolp v) - (format "Customize variable: (default %s) " v) - "Customize variable: ") - obarray (lambda (symbol) - (and (boundp symbol) - (or (get symbol 'custom-type) - (user-variable-p symbol)))))) - (list (if (equal val "") - (if (symbolp v) v nil) - (intern val))))) - -;; Here we take not only the actual groups, but the loads, too. -(defun custom-group-prompt (prompt) - "Read group from minibuffer." - (let ((completion-ignore-case t)) - (list (completing-read - prompt obarray - (lambda (symbol) - (or (get symbol 'custom-group) - (get symbol 'custom-loads))) - t)))) - -(defun custom-menu-filter (menu widget) - "Convert MENU to the form used by `widget-choose'. -MENU should be in the same format as `custom-variable-menu'. -WIDGET is the widget to apply the filter entries of MENU on." - (let ((result nil) - current name action filter) - (while menu - (setq current (car menu) - name (nth 0 current) - action (nth 1 current) - filter (nth 2 current) - menu (cdr menu)) - (if (or (null filter) (funcall filter widget)) - (push (cons name action) result) - (push name result))) - (nreverse result))) - - -;;; Unlispify. - -(defvar custom-prefix-list nil - "List of prefixes that should be ignored by `custom-unlispify'") - -(defcustom custom-unlispify-menu-entries t - "Display menu entries as words instead of symbols if non nil." - :group 'custom-menu - :type 'boolean) - -(defcustom custom-unlispify-remove-prefixes t - "Non-nil means remove group prefixes from option names in buffers and menus." - :group 'custom-menu - :type 'boolean) - -(defun custom-unlispify-menu-entry (symbol &optional no-suffix) - "Convert symbol into a menu entry." - (cond ((not custom-unlispify-menu-entries) - (symbol-name symbol)) - ((get symbol 'custom-tag) - (if no-suffix - (get symbol 'custom-tag) - (concat (get symbol 'custom-tag) "..."))) - (t - (with-current-buffer (get-buffer-create " *Custom-Work*") - (erase-buffer) - (princ symbol (current-buffer)) - (goto-char (point-min)) - (when (and (eq (get symbol 'custom-type) 'boolean) - (re-search-forward "-p\\'" nil t)) - (replace-match "" t t) - (goto-char (point-min))) - (when custom-unlispify-remove-prefixes - (let ((prefixes custom-prefix-list) - prefix) - (while prefixes - (setq prefix (car prefixes)) - (if (search-forward prefix (+ (point) (length prefix)) t) - (progn - (setq prefixes nil) - (delete-region (point-min) (point))) - (setq prefixes (cdr prefixes)))))) - (subst-char-in-region (point-min) (point-max) ?- ?\ t) - (capitalize-region (point-min) (point-max)) - (unless no-suffix - (goto-char (point-max)) - (insert "...")) - (buffer-string))))) - -(defcustom custom-unlispify-tag-names t - "Display tag names as words instead of symbols if non nil." - :group 'custom-buffer - :type 'boolean) - -(defun custom-unlispify-tag-name (symbol) - "Convert symbol into a menu entry." - (let ((custom-unlispify-menu-entries custom-unlispify-tag-names)) - (custom-unlispify-menu-entry symbol t))) - -(defun custom-prefix-add (symbol prefixes) - ;; Addd SYMBOL to list of ignored PREFIXES. - (cons (or (get symbol 'custom-prefix) - (concat (symbol-name symbol) "-")) - prefixes)) - - -;;; Guess. - -(defcustom custom-guess-name-alist - '(("-p\\'" boolean) - ("-hooks?\\'" hook) - ("-face\\'" face) - ("-file\\'" file) - ("-function\\'" function) - ("-functions\\'" (repeat function)) - ("-list\\'" (repeat sexp)) - ("-alist\\'" (repeat (cons sexp sexp)))) - "Alist of (MATCH TYPE). - -MATCH should be a regexp matching the name of a symbol, and TYPE should -be a widget suitable for editing the value of that symbol. The TYPE -of the first entry where MATCH matches the name of the symbol will be -used. - -This is used for guessing the type of variables not declared with -customize." - :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type"))) - :group 'customize) - -(defcustom custom-guess-doc-alist - '(("\\`\\*?Non-nil " boolean)) - "Alist of (MATCH TYPE). - -MATCH should be a regexp matching a documentation string, and TYPE -should be a widget suitable for editing the value of a variable with -that documentation string. The TYPE of the first entry where MATCH -matches the name of the symbol will be used. - -This is used for guessing the type of variables not declared with -customize." - :type '(repeat (group (regexp :tag "Match") (sexp :tag "Type"))) - :group 'customize) - -(defun custom-guess-type (symbol) - "Guess a widget suitable for editing the value of SYMBOL. -This is done by matching SYMBOL with `custom-guess-name-alist' and -if that fails, the doc string with `custom-guess-doc-alist'." - (let ((name (symbol-name symbol)) - (names custom-guess-name-alist) - current found) - (while names - (setq current (car names) - names (cdr names)) - (when (string-match (nth 0 current) name) - (setq found (nth 1 current) - names nil))) - (unless found - (let ((doc (documentation-property symbol 'variable-documentation)) - (docs custom-guess-doc-alist)) - (when doc - (while docs - (setq current (car docs) - docs (cdr docs)) - (when (string-match (nth 0 current) doc) - (setq found (nth 1 current) - docs nil)))))) - found)) - - -;;; Sorting. - -(defcustom custom-browse-sort-alphabetically nil - "If non-nil, sort members of each customization group alphabetically." - :type 'boolean - :group 'custom-browse) - -(defcustom custom-browse-order-groups nil - "If non-nil, order group members within each customization group. -If `first', order groups before non-groups. -If `last', order groups after non-groups." - :type '(choice (const first) - (const last) - (const :tag "none" nil)) - :group 'custom-browse) - -(defcustom custom-browse-only-groups nil - "If non-nil, show group members only within each customization group." - :type 'boolean - :group 'custom-browse) - -(defcustom custom-buffer-sort-alphabetically nil - "If non-nil, sort members of each customization group alphabetically." - :type 'boolean - :group 'custom-buffer) - -(defcustom custom-buffer-order-groups 'last - "If non-nil, order group members within each customization group. -If `first', order groups before non-groups. -If `last', order groups after non-groups." - :type '(choice (const first) - (const last) - (const :tag "none" nil)) - :group 'custom-buffer) - -(defcustom custom-menu-sort-alphabetically nil - "If non-nil, sort members of each customization group alphabetically." - :type 'boolean - :group 'custom-menu) - -(defcustom custom-menu-order-groups 'first - "If non-nil, order group members within each customization group. -If `first', order groups before non-groups. -If `last', order groups after non-groups." - :type '(choice (const first) - (const last) - (const :tag "none" nil)) - :group 'custom-menu) - -(defun custom-sort-items (items sort-alphabetically order-groups) - "Return a sorted copy of ITEMS. -ITEMS should be a `custom-group' property. -If SORT-ALPHABETICALLY non-nil, sort alphabetically. -If ORDER-GROUPS is `first' order groups before non-groups, if `last' order -groups after non-groups, if nil do not order groups at all." - (sort (copy-sequence items) - (lambda (a b) - (let ((typea (nth 1 a)) (typeb (nth 1 b)) - (namea (symbol-name (nth 0 a))) (nameb (symbol-name (nth 0 b)))) - (cond ((not order-groups) - ;; Since we don't care about A and B order, maybe sort. - (when sort-alphabetically - (string-lessp namea nameb))) - ((eq typea 'custom-group) - ;; If B is also a group, maybe sort. Otherwise, order A and B. - (if (eq typeb 'custom-group) - (when sort-alphabetically - (string-lessp namea nameb)) - (eq order-groups 'first))) - ((eq typeb 'custom-group) - ;; Since A cannot be a group, order A and B. - (eq order-groups 'last)) - (sort-alphabetically - ;; Since A and B cannot be groups, sort. - (string-lessp namea nameb))))))) - - -;;; Custom Mode Commands. - -(defvar custom-options nil - "Customization widgets in the current buffer.") - -(defun Custom-set () - "Set changes in all modified options." - (interactive) - (let ((children custom-options)) - (mapc (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-set))) - children))) - -(defun Custom-save () - "Set all modified group members and save them." - (interactive) - (let ((children custom-options)) - (mapc (lambda (child) - (when (memq (widget-get child :custom-state) '(modified set)) - (widget-apply child :custom-save))) - children)) - (custom-save-all)) - -(defvar custom-reset-menu - '(("Current" . Custom-reset-current) - ("Saved" . Custom-reset-saved) - ("Standard Settings" . Custom-reset-standard)) - "Alist of actions for the `Reset' button. -The key is a string containing the name of the action, the value is a -lisp function taking the widget as an element which will be called -when the action is chosen.") - -(defun custom-reset (event) - "Select item from reset menu." - (let* ((completion-ignore-case t) - (answer (widget-choose "Reset to" - custom-reset-menu - event))) - (if answer - (funcall answer)))) - -(defun Custom-reset-current (&rest ignore) - "Reset all modified group members to their current value." - (interactive) - (let ((children custom-options)) - (mapc (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-current))) - children))) - -(defun Custom-reset-saved (&rest ignore) - "Reset all modified or set group members to their saved value." - (interactive) - (let ((children custom-options)) - (mapc (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-saved))) - children))) - -(defun Custom-reset-standard (&rest ignore) - "Reset all modified, set, or saved group members to their standard settings." - (interactive) - (let ((children custom-options)) - (mapc (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-standard))) - children))) - - -;;; The Customize Commands - -(defun custom-prompt-variable (prompt-var prompt-val) - "Prompt for a variable and a value and return them as a list. -PROMPT-VAR is the prompt for the variable, and PROMPT-VAL is the -prompt for the value. The %s escape in PROMPT-VAL is replaced with -the name of the variable. - -If the variable has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If the variable has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value." - (let* ((var (read-variable prompt-var)) - (minibuffer-help-form '(describe-variable var))) - (list var - (let ((prop (get var 'variable-interactive)) - (type (get var 'custom-type)) - (prompt (format prompt-val var))) - (unless (listp type) - (setq type (list type))) - (cond (prop - ;; Use VAR's `variable-interactive' property - ;; as an interactive spec for prompting. - (call-interactively (list 'lambda '(arg) - (list 'interactive prop) - 'arg))) - (type - (widget-prompt-value type - prompt - (if (boundp var) - (symbol-value var)) - (not (boundp var)))) - (t - (eval-minibuffer prompt))))))) - -;;;###autoload -(defun customize-set-value (var val) - "Set VARIABLE to VALUE. VALUE is a Lisp object. - -If VARIABLE has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If VARIABLE has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value." - (interactive (custom-prompt-variable "Set variable: " - "Set %s to value: ")) - - (set var val)) - -;;;###autoload -(defun customize-set-variable (var val) - "Set the default for VARIABLE to VALUE. VALUE is a Lisp object. - -If VARIABLE has a `custom-set' property, that is used for setting -VARIABLE, otherwise `set-default' is used. - -The `customized-value' property of the VARIABLE will be set to a list -with a quoted VALUE as its sole list member. - -If VARIABLE has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If VARIABLE has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value. " - (interactive (custom-prompt-variable "Set variable: " - "Set customized value for %s to: ")) - (funcall (or (get var 'custom-set) 'set-default) var val) - (put var 'customized-value (list (custom-quote val)))) - -;;;###autoload -(defun customize-save-variable (var val) - "Set the default for VARIABLE to VALUE, and save it for future sessions. -If VARIABLE has a `custom-set' property, that is used for setting -VARIABLE, otherwise `set-default' is used. - -The `customized-value' property of the VARIABLE will be set to a list -with a quoted VALUE as its sole list member. - -If VARIABLE has a `variable-interactive' property, that is used as if -it were the arg to `interactive' (which see) to interactively read the value. - -If VARIABLE has a `custom-type' property, it must be a widget and the -`:prompt-value' property of that widget will be used for reading the value. " - (interactive (custom-prompt-variable "Set and ave variable: " - "Set and save value for %s as: ")) - (funcall (or (get var 'custom-set) 'set-default) var val) - (put var 'saved-value (list (custom-quote val))) - (custom-save-all)) - -;;;###autoload -(defun customize (group) - "Select a customization buffer which you can use to set user options. -User options are structured into \"groups\". -The default group is `Emacs'." - (interactive (custom-group-prompt - "Customize group: (default emacs) ")) - (when (stringp group) - (if (string-equal "" group) - (setq group 'emacs) - (setq group (intern group)))) - (let ((name (format "*Customize Group: %s*" - (custom-unlispify-tag-name group)))) - (if (get-buffer name) - (switch-to-buffer name) - (custom-buffer-create (list (list group 'custom-group)) - name - (concat " for group " - (custom-unlispify-tag-name group)))))) - -;;;###autoload -(defalias 'customize-group 'customize) - -;;;###autoload -(defun customize-other-window (symbol) - "Customize SYMBOL, which must be a customization group." - (interactive (custom-group-prompt - "Customize group: (default emacs) ")) - (when (stringp symbol) - (if (string-equal "" symbol) - (setq symbol 'emacs) - (setq symbol (intern symbol)))) - (custom-buffer-create-other-window - (list (list symbol 'custom-group)) - (format "*Customize Group: %s*" (custom-unlispify-tag-name symbol)))) - -;;;###autoload -(defalias 'customize-group-other-window 'customize-other-window) - -;;;###autoload -(defalias 'customize-option 'customize-variable) - -;;;###autoload -(defun customize-variable (symbol) - "Customize SYMBOL, which must be a user option variable." - (interactive (custom-variable-prompt)) - (custom-buffer-create (list (list symbol 'custom-variable)) - (format "*Customize Variable: %s*" - (custom-unlispify-tag-name symbol)))) - -;;;###autoload -(defalias 'customize-variable-other-window 'customize-option-other-window) - -;;;###autoload -(defun customize-option-other-window (symbol) - "Customize SYMBOL, which must be a user option variable. -Show the buffer in another window, but don't select it." - (interactive (custom-variable-prompt)) - (custom-buffer-create-other-window - (list (list symbol 'custom-variable)) - (format "*Customize Option: %s*" (custom-unlispify-tag-name symbol)))) - -;;;###autoload -(defun customize-face (&optional symbol) - "Customize SYMBOL, which should be a face name or nil. -If SYMBOL is nil, customize all faces." - (interactive (list (completing-read "Customize face: (default all) " - obarray 'find-face))) - (if (or (null symbol) (and (stringp symbol) (zerop (length symbol)))) - (custom-buffer-create (custom-sort-items - (mapcar (lambda (symbol) - (list symbol 'custom-face)) - (face-list)) - t nil) - "*Customize Faces*") - (when (stringp symbol) - (setq symbol (intern symbol))) - (unless (symbolp symbol) - (error "Should be a symbol %S" symbol)) - (custom-buffer-create (list (list symbol 'custom-face)) - (format "*Customize Face: %s*" - (custom-unlispify-tag-name symbol))))) - -;;;###autoload -(defun customize-face-other-window (&optional symbol) - "Show customization buffer for FACE in other window." - (interactive (list (completing-read "Customize face: " - obarray 'find-face))) - (if (or (null symbol) (and (stringp symbol) (zerop (length symbol)))) - () - (if (stringp symbol) - (setq symbol (intern symbol))) - (unless (symbolp symbol) - (error "Should be a symbol %S" symbol)) - (custom-buffer-create-other-window - (list (list symbol 'custom-face)) - (format "*Customize Face: %s*" (custom-unlispify-tag-name symbol))))) - -;;;###autoload -(defun customize-customized () - "Customize all user options set since the last save in this session." - (interactive) - (let ((found nil)) - (mapatoms (lambda (symbol) - (and (get symbol 'customized-face) - (find-face symbol) - (push (list symbol 'custom-face) found)) - (and (get symbol 'customized-value) - (boundp symbol) - (push (list symbol 'custom-variable) found)))) - (if (not found) - (error "No customized user options") - (custom-buffer-create (custom-sort-items found t nil) - "*Customize Customized*")))) - -;;;###autoload -(defun customize-saved () - "Customize all already saved user options." - (interactive) - (let ((found nil)) - (mapatoms (lambda (symbol) - (and (get symbol 'saved-face) - (find-face symbol) - (push (list symbol 'custom-face) found)) - (and (get symbol 'saved-value) - (boundp symbol) - (push (list symbol 'custom-variable) found)))) - (if (not found ) - (error "No saved user options") - (custom-buffer-create (custom-sort-items found t nil) - "*Customize Saved*")))) - -;;;###autoload -(defun customize-apropos (regexp &optional all) - "Customize all user options matching REGEXP. -If ALL is `options', include only options. -If ALL is `faces', include only faces. -If ALL is `groups', include only groups. -If ALL is t (interactively, with prefix arg), include options which are not -user-settable, as well as faces and groups." - (interactive "sCustomize regexp: \nP") - (let ((found nil)) - (mapatoms (lambda (symbol) - (when (string-match regexp (symbol-name symbol)) - (when (and (not (memq all '(faces options))) - (get symbol 'custom-group)) - (push (list symbol 'custom-group) found)) - (when (and (not (memq all '(options groups))) - (find-face symbol)) - (push (list symbol 'custom-face) found)) - (when (and (not (memq all '(groups faces))) - (boundp symbol) - (or (get symbol 'saved-value) - (get symbol 'standard-value) - (if (memq all '(nil options)) - (user-variable-p symbol) - (get symbol 'variable-documentation)))) - (push (list symbol 'custom-variable) found))))) - (if (not found) - (error "No matches") - (custom-buffer-create (custom-sort-items found t - custom-buffer-order-groups) - "*Customize Apropos*")))) - -;;;###autoload -(defun customize-apropos-options (regexp &optional arg) - "Customize all user options matching REGEXP. -With prefix arg, include options which are not user-settable." - (interactive "sCustomize regexp: \nP") - (customize-apropos regexp (or arg 'options))) - -;;;###autoload -(defun customize-apropos-faces (regexp) - "Customize all user faces matching REGEXP." - (interactive "sCustomize regexp: \n") - (customize-apropos regexp 'faces)) - -;;;###autoload -(defun customize-apropos-groups (regexp) - "Customize all user groups matching REGEXP." - (interactive "sCustomize regexp: \n") - (customize-apropos regexp 'groups)) - - -;;; Buffer. - -(defcustom custom-buffer-style 'links - "Control the presentation style for customization buffers. -The value should be a symbol, one of: - -brackets: groups nest within each other with big horizontal brackets. -links: groups have links to subgroups." - :type '(radio (const :tag "brackets: Groups nest within each others" brackets) - (const :tag "links: Group have links to subgroups" links)) - :group 'custom-buffer) - -(defcustom custom-buffer-indent 3 - "Number of spaces to indent nested groups." - :type 'integer - :group 'custom-buffer) - -;;;###autoload -(defun custom-buffer-create (options &optional name description) - "Create a buffer containing OPTIONS. -Optional NAME is the name of the buffer. -OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where -SYMBOL is a customization option, and WIDGET is a widget for editing -that option." - (unless name (setq name "*Customization*")) - (kill-buffer (get-buffer-create name)) - (switch-to-buffer (get-buffer-create name)) - (custom-buffer-create-internal options description)) - -;;;###autoload -(defun custom-buffer-create-other-window (options &optional name description) - "Create a buffer containing OPTIONS. -Optional NAME is the name of the buffer. -OPTIONS should be an alist of the form ((SYMBOL WIDGET)...), where -SYMBOL is a customization option, and WIDGET is a widget for editing -that option." - (unless name (setq name "*Customization*")) - (kill-buffer (get-buffer-create name)) - (let ((window (selected-window))) - (switch-to-buffer-other-window (get-buffer-create name)) - (custom-buffer-create-internal options description) - (select-window window))) - -(defcustom custom-reset-button-menu t - "If non-nil, only show a single reset button in customize buffers. -This button will have a menu with all three reset operations." - :type 'boolean - :group 'custom-buffer) - -(defconst custom-skip-messages 5) - -(defun custom-buffer-create-internal (options &optional description) - (message "Creating customization buffer...") - (custom-mode) - (widget-insert "This is a customization buffer") - (if description - (widget-insert description)) - (widget-insert ".\n\ -Type RET or click button2 on an active field to invoke its action. -Invoke ") - (widget-create 'info-link - :tag "Help" - :help-echo "Read the online help" - "(XEmacs)Easy Customization") - (widget-insert " for more information.\n\n") - (message "Creating customization buttons...") - (widget-insert "Operate on everything in this buffer:\n ") - (widget-create 'push-button - :tag "Set" - :tag-glyph '("set-up" "set-down") - :help-echo "\ -Make your editing in this buffer take effect for this session" - :action (lambda (widget &optional event) - (Custom-set))) - (widget-insert " ") - (widget-create 'push-button - :tag "Save" - :tag-glyph '("save-up" "save-down") - :help-echo "\ -Make your editing in this buffer take effect for future Emacs sessions" - :action (lambda (widget &optional event) - (Custom-save))) - (if custom-reset-button-menu - (progn - (widget-insert " ") - (widget-create 'push-button - :tag "Reset" - :tag-glyph '("reset-up" "reset-down") - :help-echo "Show a menu with reset operations" - :mouse-down-action (lambda (&rest junk) t) - :action (lambda (widget &optional event) - (custom-reset event)))) - (widget-insert " ") - (widget-create 'push-button - :tag "Reset" - :help-echo "\ -Reset all edited text in this buffer to reflect current values" - :action 'Custom-reset-current) - (widget-insert " ") - (widget-create 'push-button - :tag "Reset to Saved" - :help-echo "\ -Reset all values in this buffer to their saved settings" - :action 'Custom-reset-saved) - (widget-insert " ") - (widget-create 'push-button - :tag "Reset to Standard" - :help-echo "\ -Reset all values in this buffer to their standard settings" - :action 'Custom-reset-standard)) - (widget-insert " ") - (widget-create 'push-button - :tag "Done" - :tag-glyph '("done-up" "done-down") - :help-echo "Bury the buffer" - :action (lambda (widget &optional event) - (bury-buffer))) - (widget-insert "\n\n") - (message "Creating customization items...") - (setq custom-options - (if (= (length options) 1) - (mapcar (lambda (entry) - (widget-create (nth 1 entry) - :documentation-shown t - :custom-state 'unknown - :tag (custom-unlispify-tag-name - (nth 0 entry)) - :value (nth 0 entry))) - options) - (let ((count 0) - (length (length options))) - (mapcar (lambda (entry) - (prog2 - (display-message - 'progress - (format "Creating customization items %2d%%..." - (/ (* 100.0 count) length))) - (widget-create (nth 1 entry) - :tag (custom-unlispify-tag-name - (nth 0 entry)) - :value (nth 0 entry)) - (incf count) - (unless (eq (preceding-char) ?\n) - (widget-insert "\n")) - (widget-insert "\n"))) - options)))) - (unless (eq (preceding-char) ?\n) - (widget-insert "\n")) - (display-message 'progress - (format - "Creating customization items %2d%%...done" 100)) - (unless (eq custom-buffer-style 'tree) - (mapc 'custom-magic-reset custom-options)) - (message "Creating customization setup...") - (widget-setup) - (goto-char (point-min)) - (message "Creating customization buffer...done")) - - -;;; The Tree Browser. - -;;;###autoload -(defun customize-browse (&optional group) - "Create a tree browser for the customize hierarchy." - (interactive) - (unless group - (setq group 'emacs)) - (let ((name "*Customize Browser*")) - (kill-buffer (get-buffer-create name)) - (switch-to-buffer (get-buffer-create name))) - (custom-mode) - (widget-insert "\ -Square brackets show active fields; type RET or click button2 -on an active field to invoke its action. -Invoke [+] below to expand a group, and [-] to collapse an expanded group.\n") - (if custom-browse-only-groups - (widget-insert "\ -Invoke the [Group] button below to edit that item in another window.\n\n") - (widget-insert "Invoke the ") - (widget-create 'item - :format "%t" - :tag "[Group]" - :tag-glyph "folder") - (widget-insert ", ") - (widget-create 'item - :format "%t" - :tag "[Face]" - :tag-glyph "face") - (widget-insert ", and ") - (widget-create 'item - :format "%t" - :tag "[Option]" - :tag-glyph "option") - (widget-insert " buttons below to edit that -item in another window.\n\n")) - (let ((custom-buffer-style 'tree)) - (widget-create 'custom-group - :custom-last t - :custom-state 'unknown - :tag (custom-unlispify-tag-name group) - :value group)) - (goto-char (point-min))) - -(define-widget 'custom-browse-visibility 'item - "Control visibility of of items in the customize tree browser." - :format "%[[%t]%]" - :action 'custom-browse-visibility-action) - -(defun custom-browse-visibility-action (widget &rest ignore) - (let ((custom-buffer-style 'tree)) - (custom-toggle-parent widget))) - -(define-widget 'custom-browse-group-tag 'push-button - "Show parent in other window when activated." - :tag "Group" - :tag-glyph "folder" - :action 'custom-browse-group-tag-action) - -(defun custom-browse-group-tag-action (widget &rest ignore) - (let ((parent (widget-get widget :parent))) - (customize-group-other-window (widget-value parent)))) - -(define-widget 'custom-browse-variable-tag 'push-button - "Show parent in other window when activated." - :tag "Option" - :tag-glyph "option" - :action 'custom-browse-variable-tag-action) - -(defun custom-browse-variable-tag-action (widget &rest ignore) - (let ((parent (widget-get widget :parent))) - (customize-variable-other-window (widget-value parent)))) - -(define-widget 'custom-browse-face-tag 'push-button - "Show parent in other window when activated." - :tag "Face" - :tag-glyph "face" - :action 'custom-browse-face-tag-action) - -(defun custom-browse-face-tag-action (widget &rest ignore) - (let ((parent (widget-get widget :parent))) - (customize-face-other-window (widget-value parent)))) - -(defconst custom-browse-alist '((" " "space") - (" | " "vertical") - ("-\\ " "top") - (" |-" "middle") - (" `-" "bottom"))) - -(defun custom-browse-insert-prefix (prefix) - "Insert PREFIX. On XEmacs convert it to line graphics." - ;; ### Unfinished. - (if nil ; (string-match "XEmacs" emacs-version) - (progn - (insert "*") - (while (not (string-equal prefix "")) - (let ((entry (substring prefix 0 3))) - (setq prefix (substring prefix 3)) - (let ((overlay (make-overlay (1- (point)) (point) nil t nil)) - (name (nth 1 (assoc entry custom-browse-alist)))) - (overlay-put overlay 'end-glyph (widget-glyph-find name entry)) - (overlay-put overlay 'start-open t) - (overlay-put overlay 'end-open t))))) - (insert prefix))) - - -;;; Modification of Basic Widgets. -;; -;; We add extra properties to the basic widgets needed here. This is -;; fine, as long as we are careful to stay within out own namespace. -;; -;; We want simple widgets to be displayed by default, but complex -;; widgets to be hidden. - -(widget-put (get 'item 'widget-type) :custom-show t) -(widget-put (get 'editable-field 'widget-type) - :custom-show (lambda (widget value) - (let ((pp (pp-to-string value))) - (cond ((string-match "\n" pp) - nil) - ((> (length pp) 40) - nil) - (t t))))) -(widget-put (get 'menu-choice 'widget-type) :custom-show t) - -;;; The `custom-manual' Widget. - -(define-widget 'custom-manual 'info-link - "Link to the manual entry for this customization option." - :tag "Manual") - -;;; The `custom-magic' Widget. - -(defgroup custom-magic-faces nil - "Faces used by the magic button." - :group 'custom-faces - :group 'custom-buffer) - -(defface custom-invalid-face '((((class color)) - (:foreground "yellow" :background "red")) - (t - (:bold t :italic t :underline t))) - "Face used when the customize item is invalid." - :group 'custom-magic-faces) - -(defface custom-rogue-face '((((class color)) - (:foreground "pink" :background "black")) - (t - (:underline t))) - "Face used when the customize item is not defined for customization." - :group 'custom-magic-faces) - -(defface custom-modified-face '((((class color)) - (:foreground "white" :background "blue")) - (t - (:italic t :bold))) - "Face used when the customize item has been modified." - :group 'custom-magic-faces) - -(defface custom-set-face '((((class color)) - (:foreground "blue" :background "white")) - (t - (:italic t))) - "Face used when the customize item has been set." - :group 'custom-magic-faces) - -(defface custom-changed-face '((((class color)) - (:foreground "white" :background "blue")) - (t - (:italic t))) - "Face used when the customize item has been changed." - :group 'custom-magic-faces) - -(defface custom-saved-face '((t (:underline t))) - "Face used when the customize item has been saved." - :group 'custom-magic-faces) - -(defconst custom-magic-alist '((nil "#" underline "\ -uninitialized, you should not see this.") - (unknown "?" italic "\ -unknown, you should not see this.") - (hidden "-" default "\ -hidden, invoke \"Show\" button in the previous line to show." "\ -group now hidden, invoke the above \"Show\" button to show contents.") - (invalid "x" custom-invalid-face "\ -the value displayed for this %c is invalid and cannot be set.") - (modified "*" custom-modified-face "\ -you have edited the value as text, but you have not set the %c." "\ -you have edited something in this group, but not set it.") - (set "+" custom-set-face "\ -you have set this %c, but not saved it for future sessions." "\ -something in this group has been set, but not saved.") - (changed ":" custom-changed-face "\ -this %c has been changed outside the customize buffer." "\ -something in this group has been changed outside customize.") - (saved "!" custom-saved-face "\ -this %c has been set and saved." "\ -something in this group has been set and saved.") - (rogue "@" custom-rogue-face "\ -this %c has not been changed with customize." "\ -something in this group is not prepared for customization.") - (standard " " nil "\ -this %c is unchanged from its standard setting." "\ -visible group members are all at standard settings.")) - "Alist of customize option states. -Each entry is of the form (STATE MAGIC FACE ITEM-DESC [ GROUP-DESC ]), where - -STATE is one of the following symbols: - -`nil' - For internal use, should never occur. -`unknown' - For internal use, should never occur. -`hidden' - This item is not being displayed. -`invalid' - This item is modified, but has an invalid form. -`modified' - This item is modified, and has a valid form. -`set' - This item has been set but not saved. -`changed' - The current value of this item has been changed temporarily. -`saved' - This item is marked for saving. -`rogue' - This item has no customization information. -`standard' - This item is unchanged from the standard setting. - -MAGIC is a string used to present that state. - -FACE is a face used to present the state. - -ITEM-DESC is a string describing the state for options. - -GROUP-DESC is a string describing the state for groups. If this is -left out, ITEM-DESC will be used. - -The string %c in either description will be replaced with the -category of the item. These are `group'. `option', and `face'. - -The list should be sorted most significant first.") - -(defcustom custom-magic-show 'long - "If non-nil, show textual description of the state. -If `long', show a full-line description, not just one word." - :type '(choice (const :tag "no" nil) - (const short) - (const long)) - :group 'custom-buffer) - -(defcustom custom-magic-show-hidden '(option face) - "Control whether the State button is shown for hidden items. -The value should be a list with the custom categories where the State -button should be visible. Possible categories are `group', `option', -and `face'." - :type '(set (const group) (const option) (const face)) - :group 'custom-buffer) - -(defcustom custom-magic-show-button nil - "Show a \"magic\" button indicating the state of each customization option." - :type 'boolean - :group 'custom-buffer) - -(define-widget 'custom-magic 'default - "Show and manipulate state for a customization option." - :format "%v" - :action 'widget-parent-action - :notify 'ignore - :value-get 'ignore - :value-create 'custom-magic-value-create - :value-delete 'widget-children-value-delete) - -(defun widget-magic-mouse-down-action (widget &optional event) - ;; Non-nil unless hidden. - (not (eq (widget-get (widget-get (widget-get widget :parent) :parent) - :custom-state) - 'hidden))) - -(defun custom-magic-value-create (widget) - ;; Create compact status report for WIDGET. - (let* ((parent (widget-get widget :parent)) - (state (widget-get parent :custom-state)) - (hidden (eq state 'hidden)) - (entry (assq state custom-magic-alist)) - (magic (nth 1 entry)) - (face (nth 2 entry)) - (category (widget-get parent :custom-category)) - (text (or (and (eq category 'group) - (nth 4 entry)) - (nth 3 entry))) - (form (widget-get parent :custom-form)) - children) - (while (string-match "\\`\\(.*\\)%c\\(.*\\)\\'" text) - (setq text (concat (match-string 1 text) - (symbol-name category) - (match-string 2 text)))) - (when (and custom-magic-show - (or (not hidden) - (memq category custom-magic-show-hidden))) - (insert " ") - (when (and (eq category 'group) - (not (and (eq custom-buffer-style 'links) - (> (widget-get parent :custom-level) 1)))) - (insert-char ?\ (* custom-buffer-indent - (widget-get parent :custom-level)))) - (push (widget-create-child-and-convert - widget 'choice-item - :help-echo "Change the state of this item" - :format (if hidden "%t" "%[%t%]") - :button-prefix 'widget-push-button-prefix - :button-suffix 'widget-push-button-suffix - :mouse-down-action 'widget-magic-mouse-down-action - :tag "State" - ;;:tag-glyph (or hidden '("state-up" "state-down")) - ) - children) - (insert ": ") - (let ((start (point))) - (if (eq custom-magic-show 'long) - (insert text) - (insert (symbol-name state))) - (cond ((eq form 'lisp) - (insert " (lisp)")) - ((eq form 'mismatch) - (insert " (mismatch)"))) - (put-text-property start (point) 'face 'custom-state-face)) - (insert "\n")) - (when (and (eq category 'group) - (not (and (eq custom-buffer-style 'links) - (> (widget-get parent :custom-level) 1)))) - (insert-char ?\ (* custom-buffer-indent - (widget-get parent :custom-level)))) - (when custom-magic-show-button - (when custom-magic-show - (let ((indent (widget-get parent :indent))) - (when indent - (insert-char ?\ indent)))) - (push (widget-create-child-and-convert - widget 'choice-item - :mouse-down-action 'widget-magic-mouse-down-action - :button-face face - :button-prefix "" - :button-suffix "" - :help-echo "Change the state" - :format (if hidden "%t" "%[%t%]") - :tag (if (memq form '(lisp mismatch)) - (concat "(" magic ")") - (concat "[" magic "]"))) - children) - (insert " ")) - (widget-put widget :children children))) - -(defun custom-magic-reset (widget) - "Redraw the :custom-magic property of WIDGET." - (let ((magic (widget-get widget :custom-magic))) - (widget-value-set magic (widget-value magic)))) - -;;; The `custom' Widget. - -(defface custom-button-face '((t (:bold t))) - "Face used for buttons in customization buffers." - :group 'custom-faces) - -(defface custom-documentation-face nil - "Face used for documentation strings in customization buffers." - :group 'custom-faces) - -(defface custom-state-face '((((class color) - (background dark)) - (:foreground "lime green")) - (((class color) - (background light)) - (:foreground "dark green")) - (t nil)) - "Face used for State descriptions in the customize buffer." - :group 'custom-faces) - -(define-widget 'custom 'default - "Customize a user option." - :format "%v" - :convert-widget 'custom-convert-widget - :notify 'custom-notify - :custom-prefix "" - :custom-level 1 - :custom-state 'hidden - :documentation-property 'widget-subclass-responsibility - :value-create 'widget-subclass-responsibility - :value-delete 'widget-children-value-delete - :value-get 'widget-value-value-get - :validate 'widget-children-validate - :match (lambda (widget value) (symbolp value))) - -(defun custom-convert-widget (widget) - ;; Initialize :value and :tag from :args in WIDGET. - (let ((args (widget-get widget :args))) - (when args - (widget-put widget :value (widget-apply widget - :value-to-internal (car args))) - (widget-put widget :tag (custom-unlispify-tag-name (car args))) - (widget-put widget :args nil))) - widget) - -(defun custom-notify (widget &rest args) - "Keep track of changes." - (let ((state (widget-get widget :custom-state))) - (unless (eq state 'modified) - (unless (memq state '(nil unknown hidden)) - (widget-put widget :custom-state 'modified)) - (custom-magic-reset widget) - (apply 'widget-default-notify widget args)))) - -(defun custom-redraw (widget) - "Redraw WIDGET with current settings." - (let ((line (count-lines (point-min) (point))) - (column (current-column)) - (pos (point)) - (from (marker-position (widget-get widget :from))) - (to (marker-position (widget-get widget :to)))) - (save-excursion - (widget-value-set widget (widget-value widget)) - (custom-redraw-magic widget)) - (when (and (>= pos from) (<= pos to)) - (condition-case nil - (progn - (if (> column 0) - (goto-line line) - (goto-line (1+ line))) - (move-to-column column)) - (error nil))))) - -(defun custom-redraw-magic (widget) - "Redraw WIDGET state with current settings." - (while widget - (let ((magic (widget-get widget :custom-magic))) - (cond (magic - (widget-value-set magic (widget-value magic)) - (when (setq widget (widget-get widget :group)) - (custom-group-state-update widget))) - (t - (setq widget nil))))) - (widget-setup)) - -(defun custom-show (widget value) - "Non-nil if WIDGET should be shown with VALUE by default." - (let ((show (widget-get widget :custom-show))) - (cond ((null show) - nil) - ((eq t show) - t) - (t - (funcall show widget value))))) - -(defvar custom-load-recursion nil - "Hack to avoid recursive dependencies.") - -(defun custom-load-symbol (symbol) - "Load all dependencies for SYMBOL." - (unless custom-load-recursion - (let ((custom-load-recursion t) - (loads (get symbol 'custom-loads)) - load) - (while loads - (setq load (car loads) - loads (cdr loads)) - (cond ((symbolp load) - (condition-case nil - (require load) - (error nil))) - ;; Don't reload a file already loaded. - ((and (boundp 'preloaded-file-list) - (member load preloaded-file-list))) - ((assoc load load-history)) - ((assoc (locate-library load) load-history)) - (t - (condition-case nil - ;; Without this, we would load cus-edit recursively. - ;; We are still loading it when we call this, - ;; and it is not in load-history yet. - (or (equal load "cus-edit") - (load-library load)) - (error nil)))))))) - -(defun custom-load-widget (widget) - "Load all dependencies for WIDGET." - (custom-load-symbol (widget-value widget))) - -(defun custom-unloaded-symbol-p (symbol) - "Return non-nil if the dependencies of SYMBOL has not yet been loaded." - (let ((found nil) - (loads (get symbol 'custom-loads)) - load) - (while loads - (setq load (car loads) - loads (cdr loads)) - (cond ((symbolp load) - (unless (featurep load) - (setq found t))) - ((assoc load load-history)) - ((assoc (locate-library load) load-history) - ;; #### WTF??? - (message nil)) - (t - (setq found t)))) - found)) - -(defun custom-unloaded-widget-p (widget) - "Return non-nil if the dependencies of WIDGET has not yet been loaded." - (custom-unloaded-symbol-p (widget-value widget))) - -(defun custom-toggle-hide (widget) - "Toggle visibility of WIDGET." - (custom-load-widget widget) - (let ((state (widget-get widget :custom-state))) - (cond ((memq state '(invalid modified)) - (error "There are unset changes")) - ((eq state 'hidden) - (widget-put widget :custom-state 'unknown)) - (t - (widget-put widget :documentation-shown nil) - (widget-put widget :custom-state 'hidden))) - (custom-redraw widget) - (widget-setup))) - -(defun custom-toggle-parent (widget &rest ignore) - "Toggle visibility of parent of WIDGET." - (custom-toggle-hide (widget-get widget :parent))) - -(defun custom-add-see-also (widget &optional prefix) - "Add `See also ...' to WIDGET if there are any links. -Insert PREFIX first if non-nil." - (let* ((symbol (widget-get widget :value)) - (links (get symbol 'custom-links)) - (many (> (length links) 2)) - (buttons (widget-get widget :buttons)) - (indent (widget-get widget :indent))) - (when links - (when indent - (insert-char ?\ indent)) - (when prefix - (insert prefix)) - (insert "See also ") - (while links - (push (widget-create-child-and-convert widget (car links)) - buttons) - (setq links (cdr links)) - (cond ((null links) - (insert ".\n")) - ((null (cdr links)) - (if many - (insert ", and ") - (insert " and "))) - (t - (insert ", ")))) - (widget-put widget :buttons buttons)))) - -(defun custom-add-parent-links (widget &optional initial-string) - "Add \"Parent groups: ...\" to WIDGET if the group has parents. -The value if non-nil if any parents were found. -If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"." - (let ((name (widget-value widget)) - (type (widget-type widget)) - (buttons (widget-get widget :buttons)) - (start (point)) - found) - (insert (or initial-string "Parent groups:")) - (maphash (lambda (group ignore) - (let ((entry (assq name (get group 'custom-group)))) - (when (eq (nth 1 entry) type) - (insert " ") - (push (widget-create-child-and-convert - widget 'custom-group-link - :tag (custom-unlispify-tag-name group) - group) - buttons) - (setq found t)))) - custom-group-hash-table) - (widget-put widget :buttons buttons) - (if found - (insert "\n") - (delete-region start (point))) - found)) - -;;; The `custom-variable' Widget. - -(defface custom-variable-tag-face '((((class color) - (background dark)) - (:foreground "light blue" :underline t)) - (((class color) - (background light)) - (:foreground "blue" :underline t)) - (t (:underline t))) - "Face used for unpushable variable tags." - :group 'custom-faces) - -(defface custom-variable-button-face '((t (:underline t :bold t))) - "Face used for pushable variable tags." - :group 'custom-faces) - -(define-widget 'custom-variable 'custom - "Customize variable." - :format "%v" - :help-echo "Set or reset this variable" - :documentation-property 'variable-documentation - :custom-category 'option - :custom-state nil - :custom-menu 'custom-variable-menu-create - :custom-form 'edit - :value-create 'custom-variable-value-create - :action 'custom-variable-action - :custom-set 'custom-variable-set - :custom-save 'custom-variable-save - :custom-reset-current 'custom-redraw - :custom-reset-saved 'custom-variable-reset-saved - :custom-reset-standard 'custom-variable-reset-standard) - -(defun custom-variable-type (symbol) - "Return a widget suitable for editing the value of SYMBOL. -If SYMBOL has a `custom-type' property, use that. -Otherwise, look up symbol in `custom-guess-type-alist'." - (let* ((type (or (get symbol 'custom-type) - (and (not (get symbol 'standard-value)) - (custom-guess-type symbol)) - 'sexp)) - (options (get symbol 'custom-options)) - (tmp (if (listp type) - (copy-sequence type) - (list type)))) - (when options - (widget-put tmp :options options)) - tmp)) - -(defun custom-variable-value-create (widget) - "Here is where you edit the variables value." - (custom-load-widget widget) - (let* ((buttons (widget-get widget :buttons)) - (children (widget-get widget :children)) - (form (widget-get widget :custom-form)) - (state (widget-get widget :custom-state)) - (symbol (widget-get widget :value)) - (tag (widget-get widget :tag)) - (type (custom-variable-type symbol)) - (conv (widget-convert type)) - (get (or (get symbol 'custom-get) 'default-value)) - (prefix (widget-get widget :custom-prefix)) - (last (widget-get widget :custom-last)) - (value (if (default-boundp symbol) - (funcall get symbol) - (widget-get conv :value)))) - ;; If the widget is new, the child determine whether it is hidden. - (cond (state) - ((custom-show type value) - (setq state 'unknown)) - (t - (setq state 'hidden))) - ;; If we don't know the state, see if we need to edit it in lisp form. - (when (eq state 'unknown) - (unless (widget-apply conv :match value) - ;; (widget-apply (widget-convert type) :match value) - (setq form 'mismatch))) - ;; Now we can create the child widget. - (cond ((eq custom-buffer-style 'tree) - (insert prefix (if last " `--- " " |--- ")) - (push (widget-create-child-and-convert - widget 'custom-browse-variable-tag) - buttons) - (insert " " tag "\n") - (widget-put widget :buttons buttons)) - ((eq state 'hidden) - ;; Indicate hidden value. - (push (widget-create-child-and-convert - widget 'item - :format "%{%t%}: " - :sample-face 'custom-variable-tag-face - :tag tag - :parent widget) - buttons) - (push (widget-create-child-and-convert - widget 'visibility - :help-echo "Show the value of this option" - :action 'custom-toggle-parent - nil) - buttons)) - ((memq form '(lisp mismatch)) - ;; In lisp mode edit the saved value when possible. - (let* ((value (cond ((get symbol 'saved-value) - (car (get symbol 'saved-value))) - ((get symbol 'standard-value) - (car (get symbol 'standard-value))) - ((default-boundp symbol) - (custom-quote (funcall get symbol))) - (t - (custom-quote (widget-get conv :value)))))) - (insert (symbol-name symbol) ": ") - (push (widget-create-child-and-convert - widget 'visibility - :help-echo "Hide the value of this option" - :action 'custom-toggle-parent - t) - buttons) - (insert " ") - (push (widget-create-child-and-convert - widget 'sexp - :button-face 'custom-variable-button-face - :format "%v" - :tag (symbol-name symbol) - :parent widget - :value value) - children))) - (t - ;; Edit mode. - (let* ((format (widget-get type :format)) - tag-format value-format) - (unless (string-match ":" format) - (error "Bad format.")) - (setq tag-format (substring format 0 (match-end 0))) - (setq value-format (substring format (match-end 0))) - (push (widget-create-child-and-convert - widget 'item - :format tag-format - :action 'custom-tag-action - :help-echo "Change value of this option" - :mouse-down-action 'custom-tag-mouse-down-action - :button-face 'custom-variable-button-face - :sample-face 'custom-variable-tag-face - tag) - buttons) - (insert " ") - (push (widget-create-child-and-convert - widget 'visibility - :help-echo "Hide the value of this option" - :action 'custom-toggle-parent - t) - buttons) - (push (widget-create-child-and-convert - widget type - :format value-format - :value value) - children)))) - (unless (eq custom-buffer-style 'tree) - ;; Now update the state. - (unless (eq (preceding-char) ?\n) - (widget-insert "\n")) - (if (eq state 'hidden) - (widget-put widget :custom-state state) - (custom-variable-state-set widget)) - ;; Create the magic button. - (let ((magic (widget-create-child-and-convert - widget 'custom-magic nil))) - (widget-put widget :custom-magic magic) - (push magic buttons)) - ;; Update properties. - (widget-put widget :custom-form form) - (widget-put widget :buttons buttons) - (widget-put widget :children children) - ;; Insert documentation. - (widget-default-format-handler widget ?h) - ;; See also. - (unless (eq state 'hidden) - (when (eq (widget-get widget :custom-level) 1) - (custom-add-parent-links widget)) - (custom-add-see-also widget))))) - -(defun custom-tag-action (widget &rest args) - "Pass :action to first child of WIDGET's parent." - (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children)) - :action args)) - -(defun custom-tag-mouse-down-action (widget &rest args) - "Pass :mouse-down-action to first child of WIDGET's parent." - (apply 'widget-apply (car (widget-get (widget-get widget :parent) :children)) - :mouse-down-action args)) - -(defun custom-variable-state-set (widget) - "Set the state of WIDGET." - (let* ((symbol (widget-value widget)) - (get (or (get symbol 'custom-get) 'default-value)) - (value (if (default-boundp symbol) - (funcall get symbol) - (widget-get widget :value))) - tmp - (state (cond ((setq tmp (get symbol 'customized-value)) - (if (condition-case nil - (equal value (eval (car tmp))) - (error nil)) - 'set - 'changed)) - ((setq tmp (get symbol 'saved-value)) - (if (condition-case nil - (equal value (eval (car tmp))) - (error nil)) - 'saved - 'changed)) - ((setq tmp (get symbol 'standard-value)) - (if (condition-case nil - (equal value (eval (car tmp))) - (error nil)) - 'standard - 'changed)) - (t 'rogue)))) - (widget-put widget :custom-state state))) - -(defvar custom-variable-menu - '(("Set for Current Session" custom-variable-set - (lambda (widget) - (eq (widget-get widget :custom-state) 'modified))) - ("Save for Future Sessions" custom-variable-save - (lambda (widget) - (memq (widget-get widget :custom-state) '(modified set changed rogue)))) - ("Reset to Current" custom-redraw - (lambda (widget) - (and (default-boundp (widget-value widget)) - (memq (widget-get widget :custom-state) '(modified changed))))) - ("Reset to Saved" custom-variable-reset-saved - (lambda (widget) - (and (get (widget-value widget) 'saved-value) - (memq (widget-get widget :custom-state) - '(modified set changed rogue))))) - ("Reset to Standard Settings" custom-variable-reset-standard - (lambda (widget) - (and (get (widget-value widget) 'standard-value) - (memq (widget-get widget :custom-state) - '(modified set changed saved rogue))))) - ("---" ignore ignore) - ("Don't show as Lisp expression" custom-variable-edit - (lambda (widget) - (eq (widget-get widget :custom-form) 'lisp))) - ("Show as Lisp expression" custom-variable-edit-lisp - (lambda (widget) - (eq (widget-get widget :custom-form) 'edit)))) - "Alist of actions for the `custom-variable' widget. -Each entry has the form (NAME ACTION FILTER) where NAME is the name of -the menu entry, ACTION is the function to call on the widget when the -menu is selected, and FILTER is a predicate which takes a `custom-variable' -widget as an argument, and returns non-nil if ACTION is valid on that -widget. If FILTER is nil, ACTION is always valid.") - -(defun custom-variable-action (widget &optional event) - "Show the menu for `custom-variable' WIDGET. -Optional EVENT is the location for the menu." - (if (eq (widget-get widget :custom-state) 'hidden) - (custom-toggle-hide widget) - (unless (eq (widget-get widget :custom-state) 'modified) - (custom-variable-state-set widget)) - ;; Redrawing magic also depresses the state glyph. - ;(custom-redraw-magic widget) - (let* ((completion-ignore-case t) - (answer (widget-choose (concat "Operation on " - (custom-unlispify-tag-name - (widget-get widget :value))) - (custom-menu-filter custom-variable-menu - widget) - event))) - (if answer - (funcall answer widget))))) - -(defun custom-variable-edit (widget) - "Edit value of WIDGET." - (widget-put widget :custom-state 'unknown) - (widget-put widget :custom-form 'edit) - (custom-redraw widget)) - -(defun custom-variable-edit-lisp (widget) - "Edit the lisp representation of the value of WIDGET." - (widget-put widget :custom-state 'unknown) - (widget-put widget :custom-form 'lisp) - (custom-redraw widget)) - -(defun custom-variable-set (widget) - "Set the current value for the variable being edited by WIDGET." - (let* ((form (widget-get widget :custom-form)) - (state (widget-get widget :custom-state)) - (child (car (widget-get widget :children))) - (symbol (widget-value widget)) - (set (or (get symbol 'custom-set) 'set-default)) - val) - (cond ((eq state 'hidden) - (error "Cannot set hidden variable.")) - ((setq val (widget-apply child :validate)) - (goto-char (widget-get val :from)) - (error "%s" (widget-get val :error))) - ((memq form '(lisp mismatch)) - (funcall set symbol (eval (setq val (widget-value child)))) - (put symbol 'customized-value (list val))) - (t - (funcall set symbol (setq val (widget-value child))) - (put symbol 'customized-value (list (custom-quote val))))) - (custom-variable-state-set widget) - (custom-redraw-magic widget))) - -(defun custom-variable-save (widget) - "Set and save the value for the variable being edited by WIDGET." - (let* ((form (widget-get widget :custom-form)) - (state (widget-get widget :custom-state)) - (child (car (widget-get widget :children))) - (symbol (widget-value widget)) - (set (or (get symbol 'custom-set) 'set-default)) - val) - (cond ((eq state 'hidden) - (error "Cannot set hidden variable.")) - ((setq val (widget-apply child :validate)) - (goto-char (widget-get val :from)) - (error "%s" (widget-get val :error))) - ((memq form '(lisp mismatch)) - (put symbol 'saved-value (list (widget-value child))) - (funcall set symbol (eval (widget-value child)))) - (t - (put symbol - 'saved-value (list (custom-quote (widget-value - child)))) - (funcall set symbol (widget-value child)))) - (put symbol 'customized-value nil) - (custom-save-all) - (custom-variable-state-set widget) - (custom-redraw-magic widget))) - -(defun custom-variable-reset-saved (widget) - "Restore the saved value for the variable being edited by WIDGET." - (let* ((symbol (widget-value widget)) - (set (or (get symbol 'custom-set) 'set-default))) - (if (get symbol 'saved-value) - (condition-case nil - (funcall set symbol (eval (car (get symbol 'saved-value)))) - (error nil)) - (error "No saved value for %s" symbol)) - (put symbol 'customized-value nil) - (widget-put widget :custom-state 'unknown) - (custom-redraw widget))) - -(defun custom-variable-reset-standard (widget) - "Restore the standard setting for the variable being edited by WIDGET." - (let* ((symbol (widget-value widget)) - (set (or (get symbol 'custom-set) 'set-default))) - (if (get symbol 'standard-value) - (funcall set symbol (eval (car (get symbol 'standard-value)))) - (error "No standard setting known for %S" symbol)) - (put symbol 'customized-value nil) - (when (get symbol 'saved-value) - (put symbol 'saved-value nil) - (custom-save-all)) - (widget-put widget :custom-state 'unknown) - (custom-redraw widget))) - -;;; The `custom-face-edit' Widget. - -(define-widget 'custom-face-edit 'checklist - "Edit face attributes." - :format "%t: %v" - :tag "Attributes" - :extra-offset 12 - :button-args '(:help-echo "Control whether this attribute have any effect") - :args (mapcar (lambda (att) - (list 'group - :inline t - :sibling-args (widget-get (nth 1 att) :sibling-args) - (list 'const :format "" :value (nth 0 att)) - (nth 1 att))) - custom-face-attributes)) - -;;; The `custom-display' Widget. - -(define-widget 'custom-display 'menu-choice - "Select a display type." - :tag "Display" - :value t - :help-echo "Specify frames where the face attributes should be used" - :args '((const :tag "all" t) - (checklist - :offset 0 - :extra-offset 9 - :args ((group :sibling-args (:help-echo "\ -Only match the specified window systems") - (const :format "Type: " - type) - (checklist :inline t - :offset 0 - (const :format "X " - :sibling-args (:help-echo "\ -The X11 Window System") - x) - (const :format "PM " - :sibling-args (:help-echo "\ -OS/2 Presentation Manager") - pm) - (const :format "Win32 " - :sibling-args (:help-echo "\ -Windows NT/95/97") - win32) - (const :format "DOS " - :sibling-args (:help-echo "\ -Plain MS-DOS") - pc) - (const :format "TTY%n" - :sibling-args (:help-echo "\ -Plain text terminals") - tty))) - (group :sibling-args (:help-echo "\ -Only match the frames with the specified color support") - (const :format "Class: " - class) - (checklist :inline t - :offset 0 - (const :format "Color " - :sibling-args (:help-echo "\ -Match color frames") - color) - (const :format "Grayscale " - :sibling-args (:help-echo "\ -Match grayscale frames") - grayscale) - (const :format "Monochrome%n" - :sibling-args (:help-echo "\ -Match frames with no color support") - mono))) - (group :sibling-args (:help-echo "\ -Only match frames with the specified intensity") - (const :format "\ -Background brightness: " - background) - (checklist :inline t - :offset 0 - (const :format "Light " - :sibling-args (:help-echo "\ -Match frames with light backgrounds") - light) - (const :format "Dark\n" - :sibling-args (:help-echo "\ -Match frames with dark backgrounds") - dark))))))) - -;;; The `custom-face' Widget. - -(defface custom-face-tag-face '((t (:underline t))) - "Face used for face tags." - :group 'custom-faces) - -(define-widget 'custom-face 'custom - "Customize face." - :sample-face 'custom-face-tag-face - :help-echo "Set or reset this face" - :documentation-property '(lambda (face) - (face-doc-string face)) - :value-create 'custom-face-value-create - :action 'custom-face-action - :custom-category 'face - :custom-form 'selected - :custom-set 'custom-face-set - :custom-save 'custom-face-save - :custom-reset-current 'custom-redraw - :custom-reset-saved 'custom-face-reset-saved - :custom-reset-standard 'custom-face-reset-standard - :custom-menu 'custom-face-menu-create) - -(define-widget 'custom-face-all 'editable-list - "An editable list of display specifications and attributes." - :entry-format "%i %d %v" - :insert-button-args '(:help-echo "Insert new display specification here") - :append-button-args '(:help-echo "Append new display specification here") - :delete-button-args '(:help-echo "Delete this display specification") - :args '((group :format "%v" custom-display custom-face-edit))) - -(defconst custom-face-all (widget-convert 'custom-face-all) - "Converted version of the `custom-face-all' widget.") - -(define-widget 'custom-display-unselected 'item - "A display specification that doesn't match the selected display." - :match 'custom-display-unselected-match) - -(defun custom-display-unselected-match (widget value) - "Non-nil if VALUE is an unselected display specification." - (not (face-spec-set-match-display value (selected-frame)))) - -(define-widget 'custom-face-selected 'group - "Edit the attributes of the selected display in a face specification." - :args '((repeat :format "" - :inline t - (group custom-display-unselected sexp)) - (group (sexp :format "") custom-face-edit) - (repeat :format "" - :inline t - sexp))) - -(defconst custom-face-selected (widget-convert 'custom-face-selected) - "Converted version of the `custom-face-selected' widget.") - -(defun custom-face-value-create (widget) - "Create a list of the display specifications for WIDGET." - (let ((buttons (widget-get widget :buttons)) - (symbol (widget-get widget :value)) - (tag (widget-get widget :tag)) - (state (widget-get widget :custom-state)) - (begin (point)) - (is-last (widget-get widget :custom-last)) - (prefix (widget-get widget :custom-prefix))) - (unless tag - (setq tag (prin1-to-string symbol))) - (cond ((eq custom-buffer-style 'tree) - (insert prefix (if is-last " `--- " " |--- ")) - (push (widget-create-child-and-convert - widget 'custom-browse-face-tag) - buttons) - (insert " " tag "\n") - (widget-put widget :buttons buttons)) - (t - ;; Create tag. - (insert tag) - (if (eq custom-buffer-style 'face) - (insert " ") - (widget-specify-sample widget begin (point)) - (insert ": ")) - ;; Sample. - (and (not (find-face symbol)) - ;; XEmacs cannot display uninitialized faces. - (make-face symbol)) - (push (widget-create-child-and-convert widget 'item - :format "(%{%t%})" - :sample-face symbol - :tag "sample") - buttons) - ;; Visibility. - (insert " ") - (push (widget-create-child-and-convert - widget 'visibility - :help-echo "Hide or show this face" - :action 'custom-toggle-parent - (not (eq state 'hidden))) - buttons) - ;; Magic. - (insert "\n") - (let ((magic (widget-create-child-and-convert - widget 'custom-magic nil))) - (widget-put widget :custom-magic magic) - (push magic buttons)) - ;; Update buttons. - (widget-put widget :buttons buttons) - ;; Insert documentation. - (widget-default-format-handler widget ?h) - ;; See also. - (unless (eq state 'hidden) - (when (eq (widget-get widget :custom-level) 1) - (custom-add-parent-links widget)) - (custom-add-see-also widget)) - ;; Editor. - (unless (eq (preceding-char) ?\n) - (insert "\n")) - (unless (eq state 'hidden) - (message "Creating face editor...") - (custom-load-widget widget) - (let* ((symbol (widget-value widget)) - (spec (or (get symbol 'saved-face) - (get symbol 'face-defface-spec) - ;; Attempt to construct it. - (list (list t (face-custom-attributes-get - symbol (selected-frame)))))) - (form (widget-get widget :custom-form)) - (indent (widget-get widget :indent)) - (edit (widget-create-child-and-convert - widget - (cond ((and (eq form 'selected) - (widget-apply custom-face-selected - :match spec)) - (when indent (insert-char ?\ indent)) - 'custom-face-selected) - ((and (not (eq form 'lisp)) - (widget-apply custom-face-all - :match spec)) - 'custom-face-all) - (t - (when indent (insert-char ?\ indent)) - 'sexp)) - :value spec))) - (custom-face-state-set widget) - (widget-put widget :children (list edit))) - (message "Creating face editor...done")))))) - -(defvar custom-face-menu - '(("Set for Current Session" custom-face-set) - ("Save for Future Sessions" custom-face-save) - ("Reset to Saved" custom-face-reset-saved - (lambda (widget) - (get (widget-value widget) 'saved-face))) - ("Reset to Standard Setting" custom-face-reset-standard - (lambda (widget) - (get (widget-value widget) 'face-defface-spec))) - ("---" ignore ignore) - ("Show all display specs" custom-face-edit-all - (lambda (widget) - (not (eq (widget-get widget :custom-form) 'all)))) - ("Just current attributes" custom-face-edit-selected - (lambda (widget) - (not (eq (widget-get widget :custom-form) 'selected)))) - ("Show as Lisp expression" custom-face-edit-lisp - (lambda (widget) - (not (eq (widget-get widget :custom-form) 'lisp))))) - "Alist of actions for the `custom-face' widget. -Each entry has the form (NAME ACTION FILTER) where NAME is the name of -the menu entry, ACTION is the function to call on the widget when the -menu is selected, and FILTER is a predicate which takes a `custom-face' -widget as an argument, and returns non-nil if ACTION is valid on that -widget. If FILTER is nil, ACTION is always valid.") - -(defun custom-face-edit-selected (widget) - "Edit selected attributes of the value of WIDGET." - (widget-put widget :custom-state 'unknown) - (widget-put widget :custom-form 'selected) - (custom-redraw widget)) - -(defun custom-face-edit-all (widget) - "Edit all attributes of the value of WIDGET." - (widget-put widget :custom-state 'unknown) - (widget-put widget :custom-form 'all) - (custom-redraw widget)) - -(defun custom-face-edit-lisp (widget) - "Edit the lisp representation of the value of WIDGET." - (widget-put widget :custom-state 'unknown) - (widget-put widget :custom-form 'lisp) - (custom-redraw widget)) - -(defun custom-face-state-set (widget) - "Set the state of WIDGET." - (let ((symbol (widget-value widget))) - (widget-put widget :custom-state (cond ((get symbol 'customized-face) - 'set) - ((get symbol 'saved-face) - 'saved) - ((get symbol 'face-defface-spec) - 'standard) - (t - 'rogue))))) - -(defun custom-face-action (widget &optional event) - "Show the menu for `custom-face' WIDGET. -Optional EVENT is the location for the menu." - (if (eq (widget-get widget :custom-state) 'hidden) - (custom-toggle-hide widget) - (let* ((completion-ignore-case t) - (symbol (widget-get widget :value)) - (answer (widget-choose (concat "Operation on " - (custom-unlispify-tag-name symbol)) - (custom-menu-filter custom-face-menu - widget) - event))) - (if answer - (funcall answer widget))))) - -(defun custom-face-set (widget) - "Make the face attributes in WIDGET take effect." - (let* ((symbol (widget-value widget)) - (child (car (widget-get widget :children))) - (value (widget-value child))) - (put symbol 'customized-face value) - (face-spec-set symbol value) - (custom-face-state-set widget) - (custom-redraw-magic widget))) - -(defun custom-face-save (widget) - "Make the face attributes in WIDGET default." - (let* ((symbol (widget-value widget)) - (child (car (widget-get widget :children))) - (value (widget-value child))) - (face-spec-set symbol value) - (put symbol 'saved-face value) - (put symbol 'customized-face nil) - (custom-face-state-set widget) - (custom-redraw-magic widget))) - -(defun custom-face-reset-saved (widget) - "Restore WIDGET to the face's default attributes." - (let* ((symbol (widget-value widget)) - (child (car (widget-get widget :children))) - (value (get symbol 'saved-face))) - (unless value - (error "No saved value for this face")) - (put symbol 'customized-face nil) - (face-spec-set symbol value) - (widget-value-set child value) - (custom-face-state-set widget) - (custom-redraw-magic widget))) - -(defun custom-face-reset-standard (widget) - "Restore WIDGET to the face's standard settings." - (let* ((symbol (widget-value widget)) - (child (car (widget-get widget :children))) - (value (get symbol 'face-defface-spec))) - (unless value - (error "No standard setting for this face")) - (put symbol 'customized-face nil) - (when (get symbol 'saved-face) - (put symbol 'saved-face nil) - (custom-save-all)) - (face-spec-set symbol value) - (widget-value-set child value) - (custom-face-state-set widget) - (custom-redraw-magic widget))) - -;;; The `face' Widget. - -(define-widget 'face 'default - "Select and customize a face." - :convert-widget 'widget-value-convert-widget - :button-prefix 'widget-push-button-prefix - :button-suffix 'widget-push-button-suffix - :format "%t: %[select face%] %v" - :tag "Face" - :value 'default - :value-create 'widget-face-value-create - :value-delete 'widget-face-value-delete - :value-get 'widget-value-value-get - :validate 'widget-children-validate - :action 'widget-face-action - :match (lambda (widget value) (symbolp value))) - -(defun widget-face-value-create (widget) - ;; Create a `custom-face' child. - (let* ((symbol (widget-value widget)) - (custom-buffer-style 'face) - (child (widget-create-child-and-convert - widget 'custom-face - :custom-level nil - :value symbol))) - (custom-magic-reset child) - (setq custom-options (cons child custom-options)) - (widget-put widget :children (list child)))) - -(defun widget-face-value-delete (widget) - ;; Remove the child from the options. - (let ((child (car (widget-get widget :children)))) - (setq custom-options (delq child custom-options)) - (widget-children-value-delete widget))) - -(defvar face-history nil - "History of entered face names.") - -(defun widget-face-action (widget &optional event) - "Prompt for a face." - (let ((answer (completing-read "Face: " - (mapcar (lambda (face) - (list (symbol-name face))) - (face-list)) - nil nil nil - 'face-history))) - (unless (zerop (length answer)) - (widget-value-set widget (intern answer)) - (widget-apply widget :notify widget event) - (widget-setup)))) - -;;; The `hook' Widget. - -(define-widget 'hook 'list - "A emacs lisp hook" - :value-to-internal (lambda (widget value) - (if (symbolp value) - (list value) - value)) - :match (lambda (widget value) - (or (symbolp value) - (widget-group-match widget value))) - :convert-widget 'custom-hook-convert-widget - :tag "Hook") - -(defun custom-hook-convert-widget (widget) - ;; Handle `:custom-options'. - (let* ((options (widget-get widget :options)) - (other `(editable-list :inline t - :entry-format "%i %d%v" - (function :format " %v"))) - (args (if options - (list `(checklist :inline t - ,@(mapcar (lambda (entry) - `(function-item ,entry)) - options)) - other) - (list other)))) - (widget-put widget :args args) - widget)) - -;;; The `custom-group-link' Widget. - -(define-widget 'custom-group-link 'link - "Show parent in other window when activated." - :help-echo 'custom-group-link-help-echo - :action 'custom-group-link-action) - -(defun custom-group-link-help-echo (widget) - (concat "Create customization buffer for the `" - (custom-unlispify-tag-name (widget-value widget)) - "' group")) - -(defun custom-group-link-action (widget &rest ignore) - (customize-group (widget-value widget))) - -;;; The `custom-group' Widget. - -(defcustom custom-group-tag-faces nil - ;; In XEmacs, this ought to play games with font size. - "Face used for group tags. -The first member is used for level 1 groups, the second for level 2, -and so forth. The remaining group tags are shown with -`custom-group-tag-face'." - :type '(repeat face) - :group 'custom-faces) - -(defface custom-group-tag-face-1 '((((class color) - (background dark)) - (:foreground "pink" :underline t)) - (((class color) - (background light)) - (:foreground "red" :underline t)) - (t (:underline t))) - "Face used for group tags.") - -(defface custom-group-tag-face '((((class color) - (background dark)) - (:foreground "light blue" :underline t)) - (((class color) - (background light)) - (:foreground "blue" :underline t)) - (t (:underline t))) - "Face used for low level group tags." - :group 'custom-faces) - -(define-widget 'custom-group 'custom - "Customize group." - :format "%v" - :sample-face-get 'custom-group-sample-face-get - :documentation-property 'group-documentation - :help-echo "Set or reset all members of this group" - :value-create 'custom-group-value-create - :action 'custom-group-action - :custom-category 'group - :custom-set 'custom-group-set - :custom-save 'custom-group-save - :custom-reset-current 'custom-group-reset-current - :custom-reset-saved 'custom-group-reset-saved - :custom-reset-standard 'custom-group-reset-standard - :custom-menu 'custom-group-menu-create) - -(defun custom-group-sample-face-get (widget) - ;; Use :sample-face. - (or (nth (1- (widget-get widget :custom-level)) custom-group-tag-faces) - 'custom-group-tag-face)) - -(define-widget 'custom-group-visibility 'visibility - "An indicator and manipulator for hidden group contents." - :create 'custom-group-visibility-create) - -(defun custom-group-visibility-create (widget) - (let ((visible (widget-value widget))) - (if visible - (insert "--------"))) - (widget-default-create widget)) - -(defun custom-group-members (symbol groups-only) - "Return SYMBOL's custom group members. -If GROUPS-ONLY non-nil, return only those members that are groups." - (if (not groups-only) - (get symbol 'custom-group) - (let (members) - (dolist (entry (get symbol 'custom-group) (nreverse members)) - (when (eq (nth 1 entry) 'custom-group) - (push entry members)))))) - -(defun custom-group-value-create (widget) - "Insert a customize group for WIDGET in the current buffer." - (let* ((state (widget-get widget :custom-state)) - (level (widget-get widget :custom-level)) - ;; (indent (widget-get widget :indent)) - (prefix (widget-get widget :custom-prefix)) - (buttons (widget-get widget :buttons)) - (tag (widget-get widget :tag)) - (symbol (widget-value widget)) - (members (custom-group-members symbol - (and (eq custom-buffer-style 'tree) - custom-browse-only-groups)))) - (cond ((and (eq custom-buffer-style 'tree) - (eq state 'hidden) - (or members (custom-unloaded-widget-p widget))) - (custom-browse-insert-prefix prefix) - (push (widget-create-child-and-convert - widget 'custom-browse-visibility - ;; :tag-glyph "plus" - :tag "+") - buttons) - (insert "-- ") - ;; (widget-glyph-insert nil "-- " "horizontal") - (push (widget-create-child-and-convert - widget 'custom-browse-group-tag) - buttons) - (insert " " tag "\n") - (widget-put widget :buttons buttons)) - ((and (eq custom-buffer-style 'tree) - (zerop (length members))) - (custom-browse-insert-prefix prefix) - (insert "[ ]-- ") - ;; (widget-glyph-insert nil "[ ]" "empty") - ;; (widget-glyph-insert nil "-- " "horizontal") - (push (widget-create-child-and-convert - widget 'custom-browse-group-tag) - buttons) - (insert " " tag "\n") - (widget-put widget :buttons buttons)) - ((eq custom-buffer-style 'tree) - (custom-browse-insert-prefix prefix) - (custom-load-widget widget) - (if (zerop (length members)) - (progn - (custom-browse-insert-prefix prefix) - (insert "[ ]-- ") - ;; (widget-glyph-insert nil "[ ]" "empty") - ;; (widget-glyph-insert nil "-- " "horizontal") - (push (widget-create-child-and-convert - widget 'custom-browse-group-tag) - buttons) - (insert " " tag "\n") - (widget-put widget :buttons buttons)) - (push (widget-create-child-and-convert - widget 'custom-browse-visibility - ;; :tag-glyph "minus" - :tag "-") - buttons) - (insert "-\\ ") - ;; (widget-glyph-insert nil "-\\ " "top") - (push (widget-create-child-and-convert - widget 'custom-browse-group-tag) - buttons) - (insert " " tag "\n") - (widget-put widget :buttons buttons) - (message "Creating group...") - (let* ((members (custom-sort-items members - custom-browse-sort-alphabetically - custom-browse-order-groups)) - (prefixes (widget-get widget :custom-prefixes)) - (custom-prefix-list (custom-prefix-add symbol prefixes)) - (extra-prefix (if (widget-get widget :custom-last) - " " - " | ")) - (prefix (concat prefix extra-prefix)) - children entry) - (while members - (setq entry (car members) - members (cdr members)) - (push (widget-create-child-and-convert - widget (nth 1 entry) - :group widget - :tag (custom-unlispify-tag-name (nth 0 entry)) - :custom-prefixes custom-prefix-list - :custom-level (1+ level) - :custom-last (null members) - :value (nth 0 entry) - :custom-prefix prefix) - children)) - (widget-put widget :children (reverse children))) - (message "Creating group...done"))) - ;; Nested style. - ((eq state 'hidden) - ;; Create level indicator. - (unless (eq custom-buffer-style 'links) - (insert-char ?\ (* custom-buffer-indent (1- level))) - (insert "-- ")) - ;; Create link indicator. - (when (eq custom-buffer-style 'links) - (insert " ") - (push (widget-create-child-and-convert - widget 'custom-group-link - :tag "Open" - :tag-glyph '("open-up" "open-down") - symbol) - buttons) - (insert " ")) - ;; Create tag. - (let ((begin (point))) - (insert tag) - (widget-specify-sample widget begin (point))) - (insert " group") - ;; Create visibility indicator. - (unless (eq custom-buffer-style 'links) - (insert ": ") - (push (widget-create-child-and-convert - widget 'custom-group-visibility - :help-echo "Show members of this group" - :action 'custom-toggle-parent - (not (eq state 'hidden))) - buttons)) - (insert " \n") - ;; Create magic button. - (let ((magic (widget-create-child-and-convert - widget 'custom-magic nil))) - (widget-put widget :custom-magic magic) - (push magic buttons)) - ;; Update buttons. - (widget-put widget :buttons buttons) - ;; Insert documentation. - (if (and (eq custom-buffer-style 'links) (> level 1)) - (widget-put widget :documentation-indent 0)) - (widget-default-format-handler widget ?h)) - ;; Nested style. - (t ;Visible. - (custom-load-widget widget) - ;; Update members - (setq members (custom-group-members - symbol (and (eq custom-buffer-style 'tree) - custom-browse-only-groups))) - ;; Add parent groups references above the group. - (if t ;;; This should test that the buffer - ;;; was made to display a group. - (when (eq level 1) - (if (custom-add-parent-links widget - "Go to parent group:") - (insert "\n")))) - ;; Create level indicator. - (insert-char ?\ (* custom-buffer-indent (1- level))) - (insert "/- ") - ;; Create tag. - (let ((start (point))) - (insert tag) - (widget-specify-sample widget start (point))) - (insert " group: ") - ;; Create visibility indicator. - (unless (eq custom-buffer-style 'links) - (insert "--------") - (push (widget-create-child-and-convert - widget 'visibility - :help-echo "Hide members of this group" - :action 'custom-toggle-parent - (not (eq state 'hidden))) - buttons) - (insert " ")) - ;; Create more dashes. - ;; Use 76 instead of 75 to compensate for the temporary "<" - ;; added by `widget-insert'. - (insert-char ?- (- 76 (current-column) - (* custom-buffer-indent level))) - (insert "\\\n") - ;; Create magic button. - (let ((magic (widget-create-child-and-convert - widget 'custom-magic - :indent 0 - nil))) - (widget-put widget :custom-magic magic) - (push magic buttons)) - ;; Update buttons. - (widget-put widget :buttons buttons) - ;; Insert documentation. - (widget-default-format-handler widget ?h) - ;; Parent groups. - (if nil ;;; This should test that the buffer - ;;; was not made to display a group. - (when (eq level 1) - (insert-char ?\ custom-buffer-indent) - (custom-add-parent-links widget))) - (custom-add-see-also widget - (make-string (* custom-buffer-indent level) - ?\ )) - ;; Members. - (message "Creating group...") - (let* ((members (custom-sort-items members - custom-buffer-sort-alphabetically - custom-buffer-order-groups)) - (prefixes (widget-get widget :custom-prefixes)) - (custom-prefix-list (custom-prefix-add symbol prefixes)) - (length (length members)) - (count 0) - (children (mapcar - (lambda (entry) - (widget-insert "\n") - (when (zerop (% count custom-skip-messages)) - (display-message - 'progress - (format "\ -Creating group members... %2d%%" - (/ (* 100.0 count) length)))) - (incf count) - (prog1 - (widget-create-child-and-convert - widget (nth 1 entry) - :group widget - :tag (custom-unlispify-tag-name - (nth 0 entry)) - :custom-prefixes custom-prefix-list - :custom-level (1+ level) - :value (nth 0 entry)) - (unless (eq (preceding-char) ?\n) - (widget-insert "\n")))) - members))) - (message "Creating group magic...") - (mapc 'custom-magic-reset children) - (message "Creating group state...") - (widget-put widget :children children) - (custom-group-state-update widget) - (message "Creating group... done")) - ;; End line - (insert "\n") - (insert-char ?\ (* custom-buffer-indent (1- level))) - (insert "\\- " (widget-get widget :tag) " group end ") - (insert-char ?- (- 75 (current-column) (* custom-buffer-indent level))) - (insert "/\n"))))) - -(defvar custom-group-menu - '(("Set for Current Session" custom-group-set - (lambda (widget) - (eq (widget-get widget :custom-state) 'modified))) - ("Save for Future Sessions" custom-group-save - (lambda (widget) - (memq (widget-get widget :custom-state) '(modified set)))) - ("Reset to Current" custom-group-reset-current - (lambda (widget) - (memq (widget-get widget :custom-state) '(modified)))) - ("Reset to Saved" custom-group-reset-saved - (lambda (widget) - (memq (widget-get widget :custom-state) '(modified set)))) - ("Reset to standard setting" custom-group-reset-standard - (lambda (widget) - (memq (widget-get widget :custom-state) '(modified set saved))))) - "Alist of actions for the `custom-group' widget. -Each entry has the form (NAME ACTION FILTER) where NAME is the name of -the menu entry, ACTION is the function to call on the widget when the -menu is selected, and FILTER is a predicate which takes a `custom-group' -widget as an argument, and returns non-nil if ACTION is valid on that -widget. If FILTER is nil, ACTION is always valid.") - -(defun custom-group-action (widget &optional event) - "Show the menu for `custom-group' WIDGET. -Optional EVENT is the location for the menu." - (if (eq (widget-get widget :custom-state) 'hidden) - (custom-toggle-hide widget) - (let* ((completion-ignore-case t) - (answer (widget-choose (concat "Operation on " - (custom-unlispify-tag-name - (widget-get widget :value))) - (custom-menu-filter custom-group-menu - widget) - event))) - (if answer - (funcall answer widget))))) - -(defun custom-group-set (widget) - "Set changes in all modified group members." - (let ((children (widget-get widget :children))) - (mapc (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-set))) - children))) - -(defun custom-group-save (widget) - "Save all modified group members." - (let ((children (widget-get widget :children))) - (mapc (lambda (child) - (when (memq (widget-get child :custom-state) '(modified set)) - (widget-apply child :custom-save))) - children))) - -(defun custom-group-reset-current (widget) - "Reset all modified group members." - (let ((children (widget-get widget :children))) - (mapc (lambda (child) - (when (eq (widget-get child :custom-state) 'modified) - (widget-apply child :custom-reset-current))) - children))) - -(defun custom-group-reset-saved (widget) - "Reset all modified or set group members." - (let ((children (widget-get widget :children))) - (mapc (lambda (child) - (when (memq (widget-get child :custom-state) '(modified set)) - (widget-apply child :custom-reset-saved))) - children))) - -(defun custom-group-reset-standard (widget) - "Reset all modified, set, or saved group members." - (let ((children (widget-get widget :children))) - (mapc (lambda (child) - (when (memq (widget-get child :custom-state) - '(modified set saved)) - (widget-apply child :custom-reset-standard))) - children))) - -(defun custom-group-state-update (widget) - "Update magic." - (unless (eq (widget-get widget :custom-state) 'hidden) - (let* ((children (widget-get widget :children)) - (states (mapcar (lambda (child) - (widget-get child :custom-state)) - children)) - (magics custom-magic-alist) - (found 'standard)) - (while magics - (let ((magic (car (car magics)))) - (if (and (not (eq magic 'hidden)) - (memq magic states)) - (setq found magic - magics nil) - (setq magics (cdr magics))))) - (widget-put widget :custom-state found))) - (custom-magic-reset widget)) - -;;; The `custom-save-all' Function. -;;;###autoload -(defcustom custom-file (if (boundp 'emacs-user-extension-dir) - (concat "~" - init-file-user - emacs-user-extension-dir - "options.el") - "~/.emacs") - "File used for storing customization information. -If you change this from the default \"~/.emacs\" you need to -explicitly load that file for the settings to take effect." - :type 'file - :group 'customize) - -(defun custom-save-delete (symbol) - "Delete the call to SYMBOL form `custom-file'. -Leave point at the location of the call, or after the last expression." - (let ((find-file-hooks nil) - (auto-mode-alist nil)) - (set-buffer (find-file-noselect custom-file))) - (goto-char (point-min)) - (catch 'found - (while t - (let ((sexp (condition-case nil - (read (current-buffer)) - (end-of-file (throw 'found nil))))) - (when (and (listp sexp) - (eq (car sexp) symbol)) - (delete-region (save-excursion - (backward-sexp) - (point)) - (point)) - (throw 'found nil)))))) - -(defun custom-save-variables () - "Save all customized variables in `custom-file'." - (save-excursion - (custom-save-delete 'custom-set-variables) - (let ((standard-output (current-buffer))) - (unless (bolp) - (princ "\n")) - (princ "(custom-set-variables") - (mapatoms (lambda (symbol) - (let ((value (get symbol 'saved-value)) - (requests (get symbol 'custom-requests)) - (now (not (or (get symbol 'standard-value) - (and (not (boundp symbol)) - (not (get symbol 'force-value))))))) - (when value - (princ "\n '(") - (princ symbol) - (princ " ") - (prin1 (car value)) - (cond (requests - (if now - (princ " t ") - (princ " nil ")) - (prin1 requests) - (princ ")")) - (now - (princ " t)")) - (t - (princ ")"))))))) - (princ ")") - (unless (looking-at "\n") - (princ "\n"))))) - -(defun custom-save-faces () - "Save all customized faces in `custom-file'." - (save-excursion - (custom-save-delete 'custom-set-faces) - (let ((standard-output (current-buffer))) - (unless (bolp) - (princ "\n")) - (princ "(custom-set-faces") - (let ((value (get 'default 'saved-face))) - ;; The default face must be first, since it affects the others. - (when value - (princ "\n '(default ") - (prin1 value) - (if (or (get 'default 'face-defface-spec) - (and (not (find-face 'default)) - (not (get 'default 'force-face)))) - (princ ")") - (princ " t)")))) - (mapatoms (lambda (symbol) - (let ((value (get symbol 'saved-face))) - (when (and (not (eq symbol 'default)) - ;; Don't print default face here. - value) - (princ "\n '(") - (princ symbol) - (princ " ") - (prin1 value) - (if (or (get symbol 'face-defface-spec) - (and (not (find-face symbol)) - (not (get symbol 'force-face)))) - (princ ")") - (princ " t)")))))) - (princ ")") - (unless (looking-at "\n") - (princ "\n"))))) - -;;;###autoload -(defun customize-save-customized () - "Save all user options which have been set in this session." - (interactive) - (mapatoms (lambda (symbol) - (let ((face (get symbol 'customized-face)) - (value (get symbol 'customized-value))) - (when face - (put symbol 'saved-face face) - (put symbol 'customized-face nil)) - (when value - (put symbol 'saved-value value) - (put symbol 'customized-value nil))))) - ;; We really should update all custom buffers here. - (custom-save-all)) - -;;;###autoload -(defun custom-save-all () - "Save all customizations in `custom-file'." - (let ((inhibit-read-only t)) - (custom-save-variables) - (custom-save-faces) - (let ((find-file-hooks nil) - (auto-mode-alist)) - (with-current-buffer (find-file-noselect custom-file) - (save-buffer))))) - - -;;; The Customize Menu. - -;;; Menu support - -(defun custom-face-menu-create (widget symbol) - "Ignoring WIDGET, create a menu entry for customization face SYMBOL." - (vector (custom-unlispify-menu-entry symbol) - `(customize-face ',symbol) - t)) - -(defun custom-variable-menu-create (widget symbol) - "Ignoring WIDGET, create a menu entry for customization variable SYMBOL." - (let ((type (get symbol 'custom-type))) - (unless (listp type) - (setq type (list type))) - (if (and type (widget-get type :custom-menu)) - (widget-apply type :custom-menu symbol) - (vector (custom-unlispify-menu-entry symbol) - `(customize-variable ',symbol) - t)))) - -;; Add checkboxes to boolean variable entries. -(widget-put (get 'boolean 'widget-type) - :custom-menu (lambda (widget symbol) - `[,(custom-unlispify-menu-entry symbol) - (customize-variable ',symbol) - :style toggle - :selected ,symbol])) - -;; XEmacs can create menus dynamically. -(defun custom-group-menu-create (widget symbol) - "Ignoring WIDGET, create a menu entry for customization group SYMBOL." - `( ,(custom-unlispify-menu-entry symbol t) - :filter (lambda (&rest junk) - (let ((item (custom-menu-create ',symbol))) - (if (listp item) - (cdr item) - (list item)))))) - -;;;###autoload -(defun custom-menu-create (symbol) - "Create menu for customization group SYMBOL. -The menu is in a format applicable to `easy-menu-define'." - (let* ((item (vector (custom-unlispify-menu-entry symbol) - `(customize-group ',symbol) - t))) - ;; Item is the entry for creating a menu buffer for SYMBOL. - ;; We may nest, if the menu is not too big. - (custom-load-symbol symbol) - (if (< (length (get symbol 'custom-group)) widget-menu-max-size) - ;; The menu is not too big. - (let ((custom-prefix-list (custom-prefix-add symbol - custom-prefix-list)) - (members (custom-sort-items (get symbol 'custom-group) - custom-menu-sort-alphabetically - custom-menu-order-groups))) - ;; Create the menu. - `(,(custom-unlispify-menu-entry symbol t) - ,item - "--" - ,@(mapcar (lambda (entry) - (widget-apply (if (listp (nth 1 entry)) - (nth 1 entry) - (list (nth 1 entry))) - :custom-menu (nth 0 entry))) - members))) - ;; The menu was too big. - item))) - -;;;###autoload -(defun customize-menu-create (symbol &optional name) - "Return a customize menu for customization group SYMBOL. -If optional NAME is given, use that as the name of the menu. -Otherwise the menu will be named `Customize'. -The format is suitable for use with `easy-menu-define'." - (unless name - (setq name "Customize")) - `(,name - :filter (lambda (&rest junk) - (cdr (custom-menu-create ',symbol))))) - -;;; The Custom Mode. - -(defvar custom-mode-map nil - "Keymap for `custom-mode'.") - -(unless custom-mode-map - (setq custom-mode-map (make-sparse-keymap)) - (set-keymap-parents custom-mode-map widget-keymap) - (suppress-keymap custom-mode-map) - (define-key custom-mode-map " " 'scroll-up) - (define-key custom-mode-map "\177" 'scroll-down) - (define-key custom-mode-map "q" 'bury-buffer) - (define-key custom-mode-map "u" 'Custom-goto-parent) - (define-key custom-mode-map "n" 'widget-forward) - (define-key custom-mode-map "p" 'widget-backward) - ;; (define-key custom-mode-map [mouse-1] 'Custom-move-and-invoke) - ) - -(defun Custom-move-and-invoke (event) - "Move to where you click, and if it is an active field, invoke it." - (interactive "e") - (mouse-set-point event) - (if (widget-event-point event) - (let* ((pos (widget-event-point event)) - (button (get-char-property pos 'button))) - (if button - (widget-button-click event))))) - -(easy-menu-define Custom-mode-menu - custom-mode-map - "Menu used in customization buffers." - `("Custom" - ,(customize-menu-create 'customize) - ["Set" Custom-set t] - ["Save" Custom-save t] - ["Reset to Current" Custom-reset-current t] - ["Reset to Saved" Custom-reset-saved t] - ["Reset to Standard Settings" Custom-reset-standard t] - ["Info" (Info-goto-node "(xemacs)Easy Customization") t])) - -(defun Custom-goto-parent () - "Go to the parent group listed at the top of this buffer. -If several parents are listed, go to the first of them." - (interactive) - (save-excursion - (goto-char (point-min)) - (if (search-forward "\nGo to parent group: " nil t) - (let* ((button (get-char-property (point) 'button)) - (parent (downcase (widget-get button :tag)))) - (customize-group parent))))) - -(defcustom custom-mode-hook nil - "Hook called when entering custom-mode." - :type 'hook - :group 'custom-buffer ) - -(defun custom-state-buffer-message (widget) - (if (eq (widget-get (widget-get widget :parent) :custom-state) 'modified) - (message - "To install your edits, invoke [State] and choose the Set operation"))) - -(defun custom-mode () - "Major mode for editing customization buffers. - -The following commands are available: - -Move to next button or editable field. \\[widget-forward] -Move to previous button or editable field. \\[widget-backward] -\\\ -Complete content of editable text field. \\[widget-complete] -\\\ -Invoke button under the mouse pointer. \\[Custom-move-and-invoke] -Invoke button under point. \\[widget-button-press] -Set all modifications. \\[Custom-set] -Make all modifications default. \\[Custom-save] -Reset all modified options. \\[Custom-reset-current] -Reset all modified or set options. \\[Custom-reset-saved] -Reset all options. \\[Custom-reset-standard] - -Entry to this mode calls the value of `custom-mode-hook' -if that value is non-nil." - (kill-all-local-variables) - (setq major-mode 'custom-mode - mode-name "Custom") - (use-local-map custom-mode-map) - (easy-menu-add Custom-mode-menu) - (make-local-variable 'custom-options) - (make-local-variable 'widget-documentation-face) - (setq widget-documentation-face 'custom-documentation-face) - (make-local-variable 'widget-button-face) - (setq widget-button-face 'custom-button-face) - (make-local-hook 'widget-edit-functions) - (add-hook 'widget-edit-functions 'custom-state-buffer-message nil t) - (run-hooks 'custom-mode-hook)) - - -;;; The End. - -(provide 'cus-edit) - -;; cus-edit.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/cus-face.el --- a/lisp/custom/cus-face.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -;;; cus-face.el -- Support for Custom faces. -;; -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Maintainer: Hrvoje Niksic -;; Keywords: help, faces -;; Version: 1.9960-x -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ - -;;; Commentary: -;; -;; See `custom.el'. - -;; This file should probably be dissolved, and code moved to faces.el, -;; like Stallman did. - -;;; Code: - -(require 'custom) - -;; To elude the warnings for font functions. -(eval-when-compile - (require 'font)) - -;;; Declaring a face. - -;;;###autoload -(defun custom-declare-face (face spec doc &rest args) - "Like `defface', but FACE is evaluated as a normal argument." - ;; (when (fboundp 'load-gc) - ;; (error "Attempt to declare a face during dump")) - (unless (get face 'face-defface-spec) - (put face 'face-defface-spec spec) - (unless (find-face face) - ;; If the user has already created the face, respect that. - (let ((value (or (get face 'saved-face) spec)) - (frames (relevant-custom-frames)) - frame) - ;; Create global face. - (make-empty-face face) - (face-display-set face value) - ;; Create frame local faces - (while frames - (setq frame (car frames) - frames (cdr frames)) - (face-display-set face value frame)) - (init-face-from-resources face))) - (when (and doc (null (face-doc-string face))) - (set-face-doc-string face doc)) - (custom-handle-all-keywords face args 'custom-face) - (run-hooks 'custom-define-hook)) - face) - -;;; Font Attributes. - -(defconst custom-face-attributes - '((:bold (boolean :tag "Bold" - :help-echo "Control whether a bold font should be used.") - custom-set-face-bold custom-face-bold) - (:italic (boolean :tag "Italic" - :help-echo "\ -Control whether an italic font should be used.") - custom-set-face-italic custom-face-italic) - (:underline (boolean :tag "Underline" - :help-echo "\ -Control whether the text should be underlined.") - set-face-underline-p face-underline-p) - (:foreground (color :tag "Foreground" - :value "" - :help-echo "Set foreground color.") - set-face-foreground face-foreground-name) - (:background (color :tag "Background" - :value "" - :help-echo "Set background color.") - set-face-background face-background-name) - ;; #### Should make it work on X - (:inverse-video (boolean :tag "Inverse" - :help-echo "\ -Control whether the text should be inverted. Works only on TTY-s") - set-face-reverse-p face-reverse-p) - (:stipple (editable-field :format "Stipple: %v" - :help-echo "Name of background bitmap file.") - set-face-background-pixmap custom-face-stipple) - (:family (editable-field :format "Font Family: %v" - :help-echo "\ -Name of font family to use (e.g. times).") - custom-set-face-font-family custom-face-font-family) - (:size (editable-field :format "Size: %v" - :help-echo "\ -Text size (e.g. 9pt or 2mm).") - custom-set-face-font-size custom-face-font-size) - (:strikethru (toggle :format "%[Strikethru%]: %v\n" - :help-echo "\ -Control whether the text should be strikethru.") - set-face-strikethru-p face-strikethru-p)) - "Alist of face attributes. - -The elements are of the form (KEY TYPE SET GET) where KEY is a symbol -identifying the attribute, TYPE is a widget type for editing the -attibute, SET is a function for setting the attribute value, and GET is a function for getiing the attribute value. - -The SET function should take three arguments, the face to modify, the -value of the attribute, and optionally the frame where the face should -be changed. - -The GET function should take two arguments, the face to examine, and -optonally the frame where the face should be examined.") - -(defun face-custom-attributes-set (face frame &rest atts) - "For FACE on FRAME set the attributes [KEYWORD VALUE].... -Each keyword should be listed in `custom-face-attributes'. - -If FRAME is nil, set the default face." - (while atts - (let* ((name (nth 0 atts)) - (value (nth 1 atts)) - (fun (nth 2 (assq name custom-face-attributes)))) - (setq atts (cdr (cdr atts))) - (condition-case nil - (funcall fun face value frame) - (error nil))))) - -(defun face-custom-attributes-get (face frame) - "For FACE on FRAME get the attributes [KEYWORD VALUE].... -Each keyword should be listed in `custom-face-attributes'. - -If FRAME is nil, use the default face." - (condition-case nil - ;; Attempt to get `font.el' from w3. - (require 'font) - (error nil)) - (let ((atts custom-face-attributes) - att result get) - (while atts - (setq att (car atts) - atts (cdr atts) - get (nth 3 att)) - (condition-case nil - ;; This may fail if w3 doesn't exists. - (when get - (let ((answer (funcall get face frame))) - (unless (equal answer (funcall get 'default frame)) - (when (widget-apply (nth 1 att) :match answer) - (setq result (cons (nth 0 att) (cons answer result))))))) - (error nil))) - result)) - -(defun custom-set-face-bold (face value &optional frame) - "Set the bold property of FACE to VALUE." - (if value - (make-face-bold face frame) - (make-face-unbold face frame))) - -;; Really, we should get rid of these font.el dependencies... They -;; are still presenting a problem with dumping the faces (font.el is -;; too bloated for us to dump). I am thinking about hacking up -;; font-like functionality myself for the sake of this file. It will -;; probably be to-the-point and more efficient. - -(defun custom-face-bold (face &rest args) - "Return non-nil if the font of FACE is bold." - (let* ((font (apply 'face-font-name face args)) - ;; Gag - (fontobj (font-create-object font))) - (font-bold-p fontobj))) - -(defun custom-set-face-italic (face value &optional frame) - "Set the italic property of FACE to VALUE." - (if value - (make-face-italic face frame) - (make-face-unitalic face frame))) - -(defun custom-face-italic (face &rest args) - "Return non-nil if the font of FACE is italic." - (let* ((font (apply 'face-font-name face args)) - ;; Gag - (fontobj (font-create-object font))) - (font-italic-p fontobj))) - -(defun custom-face-stipple (face &rest args) - "Return the name of the stipple file used for FACE." - (let ((image (apply 'specifier-instance - (face-background-pixmap face) args))) - (and image - (image-instance-file-name image)))) - -(defun custom-set-face-font-size (face size &rest args) - "Set the font of FACE to SIZE" - (let* ((font (apply 'face-font-name face args)) - ;; Gag - (fontobj (font-create-object font))) - (set-font-size fontobj size) - (apply 'font-set-face-font face fontobj args))) - -(defun custom-face-font-size (face &rest args) - "Return the size of the font of FACE as a string." - (let* ((font (apply 'face-font-name face args)) - ;; Gag - (fontobj (font-create-object font))) - (format "%s" (font-size fontobj)))) - -(defun custom-set-face-font-family (face family &rest args) - "Set the font of FACE to FAMILY." - (let* ((font (apply 'face-font-name face args)) - ;; Gag - (fontobj (font-create-object font))) - (set-font-family fontobj family) - (apply 'font-set-face-font face fontobj args))) - -(defun custom-face-font-family (face &rest args) - "Return the name of the font family of FACE." - (let* ((font (apply 'face-font-name face args)) - ;; Gag - (fontobj (font-create-object font))) - (font-family fontobj))) - -;;; Initializing. - -;;;###autoload -(defun custom-set-faces (&rest args) - "Initialize faces according to user preferences. -The arguments should be a list where each entry has the form: - - (FACE SPEC [NOW]) - -SPEC will be stored as the saved value for FACE. If NOW is present -and non-nil, FACE will also be created according to SPEC. - -See `defface' for the format of SPEC." - (while args - (let ((entry (car args))) - (if (listp entry) - (let ((face (nth 0 entry)) - (spec (nth 1 entry)) - (now (nth 2 entry))) - (put face 'saved-face spec) - (when now - (put face 'force-face t)) - (when (or now (find-face face)) - (unless (find-face face) - (make-empty-face face)) - (face-spec-set face spec)) - (setq args (cdr args))) - ;; Old format, a plist of FACE SPEC pairs. - (let ((face (nth 0 args)) - (spec (nth 1 args))) - (put face 'saved-face spec)) - (setq args (cdr (cdr args))))))) - -;;; The End. - -(provide 'cus-face) - -;; cus-face.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/cus-load.el --- a/lisp/custom/cus-load.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -;;; cus-load.el --- Batch load all available cus-load files - -;; Copyright (C) 1997 by Free Software Foundation, Inc. - -;; Author: Steven L Baur -;; Keywords: internal, help, faces - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; In FSF all of the custom loads are in a single `cus-load' file. -;; However, we have them distributed across directories, with optional -;; incremental loading. Here we simply collect the whole set. - - -;;; Code: - -(require 'custom) - - -(defun custom-add-loads (symbol list) - "Update the custom-loads list of a symbol. -This works by adding the elements from LIST to the SYMBOL's -`custom-loads' property, avoiding duplicates. Also, SYMBOL is -added to `custom-group-hash-table'." - (let ((loads (get symbol 'custom-loads))) - (dolist (el list) - (unless (member el loads) - (setq loads (nconc loads (list el))))) - (put symbol 'custom-loads loads) - (puthash symbol t custom-group-hash-table))) - -;; custom-add-loads was named custom-put (and accepted different -;; arguments) during the 20.3 beta cycle. Support it for -;; compatibility. -(defun custom-put (symbol ignored list) - (custom-add-loads symbol list)) -(make-obsolete 'custom-put 'custom-add-loads) - - -(message "Loading customization dependencies...") - -;; Garbage-collection seems to be very intensive here, and it slows -;; things down. Nuke it. -(let ((gc-cons-threshold 10000000)) - (mapc (lambda (dir) - (load (expand-file-name "custom-load" dir) t t)) - load-path)) - -(message "Loading customization dependencies...done") - -(provide 'cus-load) - -;;; cus-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/cus-start.el --- a/lisp/custom/cus-start.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -;;; cus-start.el --- define customization properties of builtins. -;; -;; Copyright (C) 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Keywords: internal - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not synched with FSF. - -;;; Commentary: -;; -;; The following code is used to define the customization properties -;; for builtin variables, and variables in the packages that are -;; preloaded /very/ early, before custom.el itself (replace.el is such -;; an example). The way it handles custom stuff is dirty, and should -;; be regarded as a last resort. DO NOT add variables here, unless -;; you know what you are doing. - -;; Must be run before the user has changed the value of any options! - - -;;; Code: - -(require 'custom) - -(defun custom-start-quote (sexp) - ;; This is copied from `cus-edit.el'. - "Quote SEXP iff it is not self quoting." - (if (or (memq sexp '(t nil)) - (and (symbolp sexp) - (eq (aref (symbol-name sexp) 0) ?:)) - (and (listp sexp) - (memq (car sexp) '(lambda))) - (stringp sexp) - (numberp sexp) - (and (fboundp 'characterp) - (characterp sexp))) - sexp - (list 'quote sexp))) - -(let ((all '(;; boolean - (abbrev-all-caps abbrev boolean) - (allow-deletion-of-last-visible-frame frames boolean) - (debug-on-quit debug boolean) - (delete-auto-save-files auto-save boolean) - (delete-exited-processes processes-basics boolean) - (indent-tabs-mode editing-basics boolean) - (load-ignore-elc-files maint boolean) - (load-warn-when-source-newer maint boolean) - (load-warn-when-source-only maint boolean) - (modifier-keys-are-sticky keyboard boolean) - (no-redraw-on-reenter display boolean) - (scroll-on-clipped-lines display boolean) - (truncate-partial-width-windows display boolean) - (visible-bell sound boolean) - (x-allow-sendevents x boolean) - (zmacs-regions editing-basics boolean) - ;; integer - (auto-save-interval auto-save integer) - (bell-volume sound integer) - (echo-keystrokes keyboard integer) - (gc-cons-threshold alloc integer) - (next-screen-context-lines display integer) - (scroll-step windows integer) - (window-min-height windows integer) - (window-min-width windows integer) - ;; object - (auto-save-file-format auto-save - (choice (const :tag "Normal" t) - (repeat (symbol :tag "Format")))) - (completion-ignored-extensions minibuffer - (repeat - (string :format "%v"))) - (debug-ignored-errors debug (repeat (choice :format "%v" - (symbol :tag "Class") - regexp))) - (debug-on-error debug (choice (const :tag "off" nil) - (const :tag "Always" t) - (repeat :menu-tag "When" - :value (nil) - (symbol - :tag "Condition")))) - (debug-on-signal debug (choice (const :tag "off" nil) - (const :tag "Always" t) - (repeat :menu-tag "When" - :value (nil) - (symbol - :tag "Condition")))) - (exec-path processes-basics (repeat - (choice :tag "Directory" - (const :tag "Default" nil) - (directory :format "%v")))) - (file-name-handler-alist data (repeat - (cons regexp - (function :tag "Handler")))) - (shell-file-name execute file) - (stack-trace-on-error debug (choice (const :tag "off" nil) - (const :tag "Always" t) - (repeat :menu-tag "When" - :value (nil) - (symbol - :tag "Condition")))) - (stack-trace-on-signal debug (choice (const :tag "off" nil) - (const :tag "Always" t) - (repeat :menu-tag "When" - :value (nil) - (symbol - :tag "Condition")))) - ;; buffer-local - (case-fold-search matching boolean) - (ctl-arrow display (choice (integer 160) - (sexp :tag "160 (default)" - :format "%t\n"))) - (fill-column fill integer) - (left-margin fill integer) - (tab-width editing-basics integer) - (truncate-lines display boolean) - ;; not documented as user-options, but should still be - ;; customizable: - (bar-cursor display (choice (const :tag "Block Cursor" nil) - (const :tag "Bar Cursor (1 pixel)" t) - (sexp :tag "Bar Cursor (2 pixels)" - :format "%t\n" 'other))) - (default-frame-plist frames (repeat - (list :inline t - :format "%v" - (symbol :tag "Parameter") - (sexp :tag "Value")))) - (disable-auto-save-when-buffer-shrinks auto-save boolean) - (find-file-use-truenames find-file boolean) - (find-file-compare-truenames find-file boolean) - (focus-follows-mouse x boolean) - (help-char keyboard character) - (max-lisp-eval-depth limits integer) - (max-specpdl-size limits integer) - (meta-prefix-char keyboard character) - (parse-sexp-ignore-comments editing-basics boolean) - (selective-display display - (choice (const :tag "off" nil) - (integer :tag "space" - :format "%v" - 1) - (const :tag "on" t))) - (selective-display-ellipses display boolean) - (signal-error-on-buffer-boundary internal boolean) - (temp-buffer-show-function - windows (radio (function-item :tag "Temp Buffers Always in Same Frame" - :format "%t\n" - show-temp-buffer-in-current-frame) - (const :tag "Temp Buffers Like Other Buffers" nil) - (function :tag "Other"))) - (undo-threshold undo integer) - (undo-high-threshold undo integer) - (words-include-escapes editing-basics boolean) - ;; These are from replace.el, which is loaded too early - ;; to be customizable. - (case-replace matching boolean) - (query-replace-highlight matching boolean) - (list-matching-lines-default-context-lines matching integer))) - this symbol group type) - (while all - (setq this (car all) - all (cdr all) - symbol (nth 0 this) - group (nth 1 this) - type (nth 2 this)) - (if (not (boundp symbol)) - ;; This is loaded so early, there is no message - (if (fboundp 'message) - ;; If variables are removed from C code, give an error here! - (message "Intrinsic `%S' not bound" symbol)) - ;; This is called before any user can have changed the value. - (put symbol 'standard-value - (list (custom-start-quote (default-value symbol)))) - ;; Add it to the right group. - (custom-add-to-group group symbol 'custom-variable) - ;; Set the type. - (put symbol 'custom-type type)))) - -;; This is to prevent it from being reloaded by `cus-load.el'. -(provide 'cus-start) - -;;; cus-start.el ends here. diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/custom-load.el --- a/lisp/custom/custom-load.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -;;; custom-load.el --- automatically extracted custom dependencies - - -;;; Code: - -(custom-add-loads 'extensions '("wid-edit")) -(custom-add-loads 'custom-buffer '("cus-edit")) -(custom-add-loads 'custom-faces '("cus-edit")) -(custom-add-loads 'widgets '("wid-browse" "wid-edit")) -(custom-add-loads 'environment '("cus-edit")) -(custom-add-loads 'custom-menu '("cus-edit")) -(custom-add-loads 'internal '("cus-edit")) -(custom-add-loads 'hypermedia '("wid-edit")) -(custom-add-loads 'applications '("cus-edit")) -(custom-add-loads 'help '("cus-edit")) -(custom-add-loads 'widget-browse '("wid-browse")) -(custom-add-loads 'widget-documentation '("wid-edit")) -(custom-add-loads 'customize '("cus-edit" "wid-edit")) -(custom-add-loads 'custom-browse '("cus-edit")) -(custom-add-loads 'abbrev '("cus-edit")) -(custom-add-loads 'programming '("cus-edit")) -(custom-add-loads 'widget-button '("wid-edit")) -(custom-add-loads 'files '("cus-edit")) -(custom-add-loads 'external '("cus-edit")) -(custom-add-loads 'development '("cus-edit")) -(custom-add-loads 'widget-faces '("wid-edit")) -(custom-add-loads 'languages '("cus-edit")) -(custom-add-loads 'custom-magic-faces '("cus-edit")) -(custom-add-loads 'faces '("cus-edit" "wid-edit")) -(custom-add-loads 'emacs '("cus-edit")) -(custom-add-loads 'processes '("cus-edit")) -(custom-add-loads 'wp '("cus-edit")) -(custom-add-loads 'editing '("cus-edit")) -(custom-add-loads 'i18n '("cus-edit")) - -;;; custom-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/custom.el --- a/lisp/custom/custom.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,398 +0,0 @@ -;;; custom.el -- Tools for declaring and initializing options. -;; -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Maintainer: Hrvoje Niksic -;; Keywords: help, faces -;; Version: 1.9960-x -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; If you want to use this code, please visit the URL above. -;; -;; This file only contain the code needed to declare and initialize -;; user options. The code to customize options is autoloaded from -;; `cus-edit.el'. -;; -;; The code implementing face declarations is in `cus-face.el' - -;;; Code: - -(require 'widget) - -(defvar custom-define-hook nil - ;; Customize information for this option is in `cus-edit.el'. - "Hook called after defining each customize option.") - -;;; The `defcustom' Macro. - -(defun custom-initialize-default (symbol value) - "Initialize SYMBOL with VALUE. -This will do nothing if symbol already has a default binding. -Otherwise, if symbol has a `saved-value' property, it will evaluate -the car of that and used as the default binding for symbol. -Otherwise, VALUE will be evaluated and used as the default binding for -symbol." - (unless (default-boundp symbol) - ;; Use the saved value if it exists, otherwise the standard setting. - (set-default symbol (if (get symbol 'saved-value) - (eval (car (get symbol 'saved-value))) - (eval value))))) - -(defun custom-initialize-set (symbol value) - "Initialize SYMBOL with VALUE. -Like `custom-initialize-default', but use the function specified by -`:set' to initialize SYMBOL." - (unless (default-boundp symbol) - (funcall (or (get symbol 'custom-set) 'set-default) - symbol - (if (get symbol 'saved-value) - (eval (car (get symbol 'saved-value))) - (eval value))))) - -(defun custom-initialize-reset (symbol value) - "Initialize SYMBOL with VALUE. -Like `custom-initialize-set', but use the function specified by -`:get' to reinitialize SYMBOL if it is already bound." - (funcall (or (get symbol 'custom-set) 'set-default) - symbol - (cond ((default-boundp symbol) - (funcall (or (get symbol 'custom-get) 'default-value) - symbol)) - ((get symbol 'saved-value) - (eval (car (get symbol 'saved-value)))) - (t - (eval value))))) - -(defun custom-initialize-changed (symbol value) - "Initialize SYMBOL with VALUE. -Like `custom-initialize-reset', but only use the `:set' function if the -not using the standard setting. Otherwise, use the `set-default'." - (cond ((default-boundp symbol) - (funcall (or (get symbol 'custom-set) 'set-default) - symbol - (funcall (or (get symbol 'custom-get) 'default-value) - symbol))) - ((get symbol 'saved-value) - (funcall (or (get symbol 'custom-set) 'set-default) - symbol - (eval (car (get symbol 'saved-value))))) - (t - (set-default symbol (eval value))))) - -(defun custom-declare-variable (symbol value doc &rest args) - "Like `defcustom', but SYMBOL and VALUE are evaluated as normal arguments." - ;; Remember the standard setting. - (put symbol 'standard-value (list value)) - ;; Maybe this option was rogue in an earlier version. It no longer is. - (when (get symbol 'force-value) - ;; It no longer is. - (put symbol 'force-value nil)) - (when doc - (put symbol 'variable-documentation doc)) - (let ((initialize 'custom-initialize-reset) - (requests nil)) - (while args - (let ((arg (car args))) - (setq args (cdr args)) - (unless (symbolp arg) - (error "Junk in args %S" args)) - (let ((keyword arg) - (value (car args))) - (unless args - (error "Keyword %s is missing an argument" keyword)) - (setq args (cdr args)) - (cond ((eq keyword :initialize) - (setq initialize value)) - ((eq keyword :set) - (put symbol 'custom-set value)) - ((eq keyword :get) - (put symbol 'custom-get value)) - ((eq keyword :require) - (setq requests (cons value requests))) - ((eq keyword :type) - (put symbol 'custom-type value)) - ((eq keyword :options) - (if (get symbol 'custom-options) - ;; Slow safe code to avoid duplicates. - (mapc (lambda (option) - (custom-add-option symbol option)) - value) - ;; Fast code for the common case. - (put symbol 'custom-options (copy-sequence value)))) - (t - (custom-handle-keyword symbol keyword value - 'custom-variable)))))) - (put symbol 'custom-requests requests) - ;; Do the actual initialization. - (funcall initialize symbol value)) - (run-hooks 'custom-define-hook) - symbol) - -(defmacro defcustom (symbol value doc &rest args) - "Declare SYMBOL as a customizable variable that defaults to VALUE. -DOC is the variable documentation. - -Neither SYMBOL nor VALUE needs to be quoted. -If SYMBOL is not already bound, initialize it to VALUE. -The remaining arguments should have the form - - [KEYWORD VALUE]... - -The following KEYWORD's are defined: - -:type VALUE should be a widget type for editing the symbols value. - The default is `sexp'. -:options VALUE should be a list of valid members of the widget type. -:group VALUE should be a customization group. - Add SYMBOL to that group. -:initialize VALUE should be a function used to initialize the - variable. It takes two arguments, the symbol and value - given in the `defcustom' call. The default is - `custom-initialize-set' -:set VALUE should be a function to set the value of the symbol. - It takes two arguments, the symbol to set and the value to - give it. The default is `set-default'. -:get VALUE should be a function to extract the value of symbol. - The function takes one argument, a symbol, and should return - the current value for that symbol. The default is - `default-value'. -:require VALUE should be a feature symbol. Each feature will be - required after initialization, of the the user have saved this - option. - -Read the section about customization in the Emacs Lisp manual for more -information." - `(custom-declare-variable (quote ,symbol) (quote ,value) ,doc ,@args)) - -;;; The `defface' Macro. - -(defmacro defface (face spec doc &rest args) - "Declare FACE as a customizable face that defaults to SPEC. -FACE does not need to be quoted. - -Third argument DOC is the face documentation. - -If FACE has been set with `custom-set-face', set the face attributes -as specified by that function, otherwise set the face attributes -according to SPEC. - -The remaining arguments should have the form - - [KEYWORD VALUE]... - -The following KEYWORDs are defined: - -:group VALUE should be a customization group. - Add FACE to that group. - -SPEC should be an alist of the form ((DISPLAY ATTS)...). - -ATTS is a list of face attributes and their values. The possible -attributes are defined in the variable `custom-face-attributes'. - -The ATTS of the first entry in SPEC where the DISPLAY matches the -frame should take effect in that frame. DISPLAY can either be the -symbol t, which will match all frames, or an alist of the form -\((REQ ITEM...)...) - -For the DISPLAY to match a FRAME, the REQ property of the frame must -match one of the ITEM. The following REQ are defined: - -`type' (the value of `window-system') - Should be one of `x' or `tty'. - -`class' (the frame's color support) - Should be one of `color', `grayscale', or `mono'. - -`background' (what color is used for the background text) - Should be one of `light' or `dark'. - -Read the section about customization in the Emacs Lisp manual for more -information." - `(custom-declare-face (quote ,face) ,spec ,doc ,@args)) - -;;; The `defgroup' Macro. - -(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)) - (pop members)) - (put symbol 'custom-group (nconc members (get symbol 'custom-group))) - (when doc - (put symbol 'group-documentation doc)) - (while args - (let ((arg (car args))) - (setq args (cdr args)) - (unless (symbolp arg) - (error "Junk in args %S" args)) - (let ((keyword arg) - (value (car args))) - (unless args - (error "Keyword %s is missing an argument" keyword)) - (setq args (cdr args)) - (cond ((eq keyword :prefix) - (put symbol 'custom-prefix value)) - (t - (custom-handle-keyword symbol keyword value - 'custom-group)))))) - (run-hooks 'custom-define-hook) - symbol) - -(defmacro defgroup (symbol members doc &rest args) - "Declare SYMBOL as a customization group containing MEMBERS. -SYMBOL does not need to be quoted. - -Third arg DOC is the group documentation. - -MEMBERS should be an alist of the form ((NAME WIDGET)...) where NAME -is a symbol and WIDGET is a widget for editing that symbol. Useful -widgets are `custom-variable' for editing variables, `custom-face' for -edit faces, and `custom-group' for editing groups. - -The remaining arguments should have the form - - [KEYWORD VALUE]... - -The following KEYWORD's are defined: - -:group VALUE should be a customization group. - Add SYMBOL to that group. - -Read the section about customization in the Emacs Lisp manual for more -information." - `(custom-declare-group (quote ,symbol) ,members ,doc ,@args)) - -;; This is preloaded very early, so we avoid using CL features. -(defvar custom-group-hash-table (make-hashtable 300 'eq) - "Hash-table of non-empty groups.") - -(defun custom-add-to-group (group option widget) - "To existing GROUP add a new OPTION of type WIDGET. -If there already is an entry for that option, overwrite it." - (let* ((members (get group 'custom-group)) - (old (assq option members))) - (if old - (setcar (cdr old) widget) - (put group 'custom-group (nconc members (list (list option widget)))))) - (puthash group t custom-group-hash-table)) - -;;; Properties. - -(defun custom-handle-all-keywords (symbol args type) - "For customization option SYMBOL, handle keyword arguments ARGS. -Third argument TYPE is the custom option type." - (while args - (let ((arg (car args))) - (setq args (cdr args)) - (unless (symbolp arg) - (error "Junk in args %S" args)) - (let ((keyword arg) - (value (car args))) - (unless args - (error "Keyword %s is missing an argument" keyword)) - (setq args (cdr args)) - (custom-handle-keyword symbol keyword value type))))) - -(defun custom-handle-keyword (symbol keyword value type) - "For customization option SYMBOL, handle KEYWORD with VALUE. -Fourth argument TYPE is the custom option type." - (cond ((eq keyword :group) - (custom-add-to-group value symbol type)) - ((eq keyword :link) - (custom-add-link symbol value)) - ((eq keyword :load) - (custom-add-load symbol value)) - ((eq keyword :tag) - (put symbol 'custom-tag value)) - (t - (error "Unknown keyword %s" symbol)))) - -(defun custom-add-option (symbol option) - "To the variable SYMBOL add OPTION. - -If SYMBOL is a hook variable, OPTION should be a hook member. -For other types variables, the effect is undefined." - (let ((options (get symbol 'custom-options))) - (unless (member option options) - (put symbol 'custom-options (cons option options))))) - -(defun custom-add-link (symbol widget) - "To the custom option SYMBOL add the link WIDGET." - (let ((links (get symbol 'custom-links))) - (unless (member widget links) - (put symbol 'custom-links (cons widget links))))) - -(defun custom-add-load (symbol load) - "To the custom option SYMBOL add the dependency LOAD. -LOAD should be either a library file name, or a feature name." - (let ((loads (get symbol 'custom-loads))) - (unless (member load loads) - (put symbol 'custom-loads (cons load loads))))) - -;;; Initializing. - -(defun custom-set-variables (&rest args) - "Initialize variables according to user preferences. - -The arguments should be a list where each entry has the form: - - (SYMBOL VALUE [NOW]) - -The unevaluated VALUE is stored as the saved value for SYMBOL. -If NOW is present and non-nil, VALUE is also evaluated and bound as -the default value for the SYMBOL." - (while args - (let ((entry (car args))) - (if (listp entry) - (let* ((symbol (nth 0 entry)) - (value (nth 1 entry)) - (now (nth 2 entry)) - (requests (nth 3 entry)) - (set (or (get symbol 'custom-set) 'set-default))) - (put symbol 'saved-value (list value)) - (cond (now - ;; Rogue variable, set it now. - (put symbol 'force-value t) - (funcall set symbol (eval value))) - ((default-boundp symbol) - ;; Something already set this, overwrite it. - (funcall set symbol (eval value)))) - (when requests - (put symbol 'custom-requests requests) - (mapc 'require requests)) - (setq args (cdr args))) - ;; Old format, a plist of SYMBOL VALUE pairs. - (message "Warning: old format `custom-set-variables'") - (ding) - (sit-for 2) - (let ((symbol (nth 0 args)) - (value (nth 1 args))) - (put symbol 'saved-value (list value))) - (setq args (cdr (cdr args))))))) - -;;; The End. - -(provide 'custom) - -;; custom.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/wid-browse.el --- a/lisp/custom/wid-browse.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,300 +0,0 @@ -;;; wid-browse.el --- Functions for browsing widgets. -;; -;; Copyright (C) 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Keywords: extensions -;; Version: 1.9960 -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; Widget browser. See `widget.el'. - -;;; Code: - -(require 'easymenu) -(require 'custom) -(require 'wid-edit) -(eval-when-compile (require 'cl)) - -(defgroup widget-browse nil - "Customization support for browsing widgets." - :group 'widgets) - -;;; The Mode. - -(defvar widget-browse-mode-map nil - "Keymap for `widget-browse-mode'.") - -(unless widget-browse-mode-map - (setq widget-browse-mode-map (make-sparse-keymap)) - (set-keymap-parent widget-browse-mode-map widget-keymap) - (define-key widget-browse-mode-map "q" 'bury-buffer)) - -(easy-menu-define widget-browse-mode-customize-menu - widget-browse-mode-map - "Menu used in widget browser buffers." - (customize-menu-create 'widgets)) - -(easy-menu-define widget-browse-mode-menu - widget-browse-mode-map - "Menu used in widget browser buffers." - '("Widget" - ["Browse" widget-browse t] - ["Browse At" widget-browse-at t])) - -(defcustom widget-browse-mode-hook nil - "Hook called when entering widget-browse-mode." - :type 'hook - :group 'widget-browse) - -(defun widget-browse-mode () - "Major mode for widget browser buffers. - -The following commands are available: - -\\[widget-forward] Move to next button or editable field. -\\[widget-backward] Move to previous button or editable field. -\\[widget-button-click] Activate button under the mouse pointer. -\\[widget-button-press] Activate button under point. - -Entry to this mode calls the value of `widget-browse-mode-hook' -if that value is non-nil." - (kill-all-local-variables) - (setq major-mode 'widget-browse-mode - mode-name "Widget") - (use-local-map widget-browse-mode-map) - (easy-menu-add widget-browse-mode-customize-menu) - (easy-menu-add widget-browse-mode-menu) - (run-hooks 'widget-browse-mode-hook)) - -;;; Commands. - -;;;###autoload -(defun widget-browse-at (pos) - "Browse the widget under point." - (interactive "d") - (let* ((field (get-char-property pos 'field)) - (button (get-char-property pos 'button)) - (doc (get-char-property pos 'widget-doc)) - (text (cond (field "This is an editable text area.") - (button "This is an active area.") - (doc "This is documentation text.") - (t "This is unidentified text."))) - (widget (or field button doc))) - (when widget - (widget-browse widget)) - (message text))) - -(defvar widget-browse-history nil) - -;;;###autoload -(defun widget-browse (widget) - "Create a widget browser for WIDGET." - (interactive (list (completing-read "Widget: " - obarray - (lambda (symbol) - (get symbol 'widget-type)) - t nil 'widget-browse-history))) - (if (stringp widget) - (setq widget (intern widget))) - (unless (if (symbolp widget) - (get widget 'widget-type) - (and (consp widget) - (get (widget-type widget) 'widget-type))) - (error "Not a widget.")) - ;; Create the buffer. - (if (symbolp widget) - (let ((buffer (format "*Browse %s Widget*" widget))) - (kill-buffer (get-buffer-create buffer)) - (switch-to-buffer (get-buffer-create buffer))) - (kill-buffer (get-buffer-create "*Browse Widget*")) - (switch-to-buffer (get-buffer-create "*Browse Widget*"))) - (widget-browse-mode) - - ;; Quick way to get out. -;; (widget-create 'push-button -;; :action (lambda (widget &optional event) -;; (bury-buffer)) -;; "Quit") -;; (widget-insert "\n") - - ;; Top text indicating whether it is a class or object browser. - (if (listp widget) - (widget-insert "Widget object browser.\n\nClass: ") - (widget-insert "Widget class browser.\n\n") - (widget-create 'widget-browse - :format "%[%v%]\n%d" - :doc (get widget 'widget-documentation) - widget) - (unless (eq (preceding-char) ?\n) - (widget-insert "\n")) - (widget-insert "\nSuper: ") - (setq widget (get widget 'widget-type))) - - ;; Now show the attributes. - (let ((name (car widget)) - (items (cdr widget)) - key value printer) - (widget-create 'widget-browse - :format "%[%v%]" - name) - (widget-insert "\n") - (while items - (setq key (nth 0 items) - value (nth 1 items) - printer (or (get key 'widget-keyword-printer) - 'widget-browse-sexp) - items (cdr (cdr items))) - (widget-insert "\n" (symbol-name key) "\n\t") - (funcall printer widget key value) - (widget-insert "\n"))) - (widget-setup) - (goto-char (point-min))) - -;;;###autoload -(defun widget-browse-other-window (&optional widget) - "Show widget browser for WIDGET in other window." - (interactive) - (let ((window (selected-window))) - (switch-to-buffer-other-window "*Browse Widget*") - (if widget - (widget-browse widget) - (call-interactively 'widget-browse)) - (select-window window))) - - -;;; The `widget-browse' Widget. - -(define-widget 'widget-browse 'push-button - "Button for creating a widget browser. -The :value of the widget shuld be the widget to be browsed." - :format "%[[%v]%]" - :value-create 'widget-browse-value-create - :action 'widget-browse-action) - -(defun widget-browse-action (widget &optional event) - ;; Create widget browser for WIDGET's :value. - (widget-browse (widget-get widget :value))) - -(defun widget-browse-value-create (widget) - ;; Insert type name. - (let ((value (widget-get widget :value))) - (cond ((symbolp value) - (insert (symbol-name value))) - ((consp value) - (insert (symbol-name (widget-type value)))) - (t - (insert "strange"))))) - -;;; Keyword Printer Functions. - -(defun widget-browse-widget (widget key value) - "Insert description of WIDGET's KEY VALUE. -VALUE is assumed to be a widget." - (widget-create 'widget-browse value)) - -(defun widget-browse-widgets (widget key value) - "Insert description of WIDGET's KEY VALUE. -VALUE is assumed to be a list of widgets." - (while value - (widget-create 'widget-browse - (car value)) - (setq value (cdr value)) - (when value - (widget-insert " ")))) - -(defun widget-browse-sexp (widget key value) - "Insert description of WIDGET's KEY VALUE. -Nothing is assumed about value." - (let ((pp (condition-case signal - (pp-to-string value) - (error (prin1-to-string signal))))) - (when (string-match "\n\\'" pp) - (setq pp (substring pp 0 (1- (length pp))))) - (if (cond ((string-match "\n" pp) - nil) - ((> (length pp) (- (window-width) (current-column))) - nil) - (t t)) - (widget-insert pp) - (widget-create 'push-button - :tag "show" - :action (lambda (widget &optional event) - (with-output-to-temp-buffer - "*Pp Eval Output*" - (princ (widget-get widget :value)))) - pp)))) - -(defun widget-browse-sexps (widget key value) - "Insert description of WIDGET's KEY VALUE. -VALUE is assumed to be a list of widgets." - (let ((target (current-column))) - (while value - (widget-browse-sexp widget key (car value)) - (setq value (cdr value)) - (when value - (widget-insert "\n" (make-string target ?\ )))))) - -;;; Keyword Printers. - -(put :parent 'widget-keyword-printer 'widget-browse-widget) -(put :children 'widget-keyword-printer 'widget-browse-widgets) -(put :buttons 'widget-keyword-printer 'widget-browse-widgets) -(put :button 'widget-keyword-printer 'widget-browse-widget) -(put :args 'widget-keyword-printer 'widget-browse-sexps) - -;;; Widget Minor Mode. - -(defvar widget-minor-mode nil - "I non-nil, we are in Widget Minor Mode.") - (make-variable-buffer-local 'widget-minor-mode) - -(defvar widget-minor-mode-map nil - "Keymap used in Widget Minor Mode.") - -(unless widget-minor-mode-map - (setq widget-minor-mode-map (make-sparse-keymap)) - (set-keymap-parent widget-minor-mode-map widget-keymap)) - -;;;###autoload -(defun widget-minor-mode (&optional arg) - "Togle minor mode for traversing widgets. -With arg, turn widget mode on if and only if arg is positive." - (interactive "P") - (cond ((null arg) - (setq widget-minor-mode (not widget-minor-mode))) - ((<= arg 0) - (setq widget-minor-mode nil)) - (t - (setq widget-minor-mode t))) - (force-mode-line-update)) - -(add-to-list 'minor-mode-alist '(widget-minor-mode " Widget")) - -(add-to-list 'minor-mode-map-alist - (cons 'widget-minor-mode widget-minor-mode-map)) - -;;; The End: - -(provide 'wid-browse) - -;; wid-browse.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/wid-edit.el --- a/lisp/custom/wid-edit.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3640 +0,0 @@ -;;; wid-edit.el --- Functions for creating and using widgets. -;; -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Maintainer: Hrvoje Niksic -;; Keywords: extensions -;; Version: 1.9960-x -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; See `widget.el'. - - -;;; Code: - -(require 'widget) - -(autoload 'pp-to-string "pp") -(autoload 'finder-commentary "finder" nil t) - -;;; Customization. - -(defgroup widgets nil - "Customization support for the Widget Library." - :link '(custom-manual "(widget)Top") - :link '(url-link :tag "Development Page" - "http://www.dina.kvl.dk/~abraham/custom/") - :link '(emacs-library-link :tag "Lisp File" "widget.el") - :prefix "widget-" - :group 'extensions - :group 'hypermedia) - -(defgroup widget-documentation nil - "Options controling the display of documentation strings." - :group 'widgets) - -(defgroup widget-faces nil - "Faces used by the widget library." - :group 'widgets - :group 'faces) - -(defvar widget-documentation-face 'widget-documentation-face - "Face used for documentation strings in widges. -This exists as a variable so it can be set locally in certain buffers.") - -(defface widget-documentation-face '((((class color) - (background dark)) - (:foreground "lime green")) - (((class color) - (background light)) - (:foreground "dark green")) - (t nil)) - "Face used for documentation text." - :group 'widget-documentation - :group 'widget-faces) - -(defvar widget-button-face 'widget-button-face - "Face used for buttons in widges. -This exists as a variable so it can be set locally in certain buffers.") - -(defface widget-button-face '((t (:bold t))) - "Face used for widget buttons." - :group 'widget-faces) - -(defcustom widget-mouse-face 'highlight - "Face used for widget buttons when the mouse is above them." - :type 'face - :group 'widget-faces) - -(defface widget-field-face '((((class grayscale color) - (background light)) - (:background "gray85")) - (((class grayscale color) - (background dark)) - (:background "dim gray")) - (t - (:italic t))) - "Face used for editable fields." - :group 'widget-faces) - -;; Currently unused -;(defface widget-single-line-field-face '((((class grayscale color) -; (background light)) -; (:background "gray85")) -; (((class grayscale color) -; (background dark)) -; (:background "dim gray")) -; (t -; (:italic t))) -; "Face used for editable fields spanning only a single line." -; :group 'widget-faces) -; -;(defvar widget-single-line-display-table -; (let ((table (make-display-table))) -; (aset table 9 "^I") -; (aset table 10 "^J") -; table) -; "Display table used for single-line editable fields.") -; -;(set-face-display-table 'widget-single-line-field-face -; widget-single-line-display-table) - - -;; Some functions from this file have been ported to C for speed. -;; Setting this to t (*before* loading wid-edit.el) will make them -;; shadow the subrs. It should be used only for debugging purposes. -(defvar widget-shadow-subrs nil) - - -;;; Utility functions. -;; -;; These are not really widget specific. - -(when (or (not (fboundp 'widget-plist-member)) - widget-shadow-subrs) - ;; Recoded in C, for efficiency. It used to be a defsubst, but old - ;; compiled code won't fail -- it will just be slower. - (defun widget-plist-member (plist prop) - ;; Return non-nil if PLIST has the property PROP. - ;; PLIST is a property list, which is a list of the form - ;; (PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol. - ;; Unlike `plist-get', this allows you to distinguish between a missing - ;; property and a property with the value nil. - ;; The value is actually the tail of PLIST whose car is PROP. - (while (and plist (not (eq (car plist) prop))) - (setq plist (cddr plist))) - plist)) - -(defun widget-princ-to-string (object) - ;; Return string representation of OBJECT, any Lisp object. - ;; No quoting characters are used; no delimiters are printed around - ;; the contents of strings. - (with-current-buffer (get-buffer-create " *widget-tmp*") - (erase-buffer) - (princ object (current-buffer)) - (buffer-string))) - -(defun widget-clear-undo () - "Clear all undo information." - (buffer-disable-undo) - (buffer-enable-undo)) - -(defcustom widget-menu-max-size 40 - "Largest number of items allowed in a popup-menu. -Larger menus are read through the minibuffer." - :group 'widgets - :type 'integer) - -(defcustom widget-menu-minibuffer-flag nil - "*Control how to ask for a choice from the keyboard. -Non-nil means use the minibuffer; -nil means read a single character." - :group 'widgets - :type 'boolean) - -(defun widget-choose (title items &optional event) - "Choose an item from a list. - -First argument TITLE is the name of the list. -Second argument ITEMS is an list whose members are either - (NAME . VALUE), to indicate selectable items, or just strings to - indicate unselectable items. -Optional third argument EVENT is an input event. - -The user is asked to choose between each NAME from the items alist, -and the VALUE of the chosen element will be returned. If EVENT is a -mouse event, and the number of elements in items is less than -`widget-menu-max-size', a popup menu will be used, otherwise the -minibuffer." - (cond ((and (< (length items) widget-menu-max-size) - event - (console-on-window-system-p)) - ;; Pressed by the mouse. - (let ((val (get-popup-menu-response - (cons title - (mapcar (lambda (x) - (if (stringp x) - (vector x nil nil) - (vector (car x) (list (car x)) t))) - items))))) - (setq val (and val - (listp (event-object val)) - (stringp (car-safe (event-object val))) - (car (event-object val)))) - (cdr (assoc val items)))) - ((and (not widget-menu-minibuffer-flag) - ;; Can't handle more than 10 items (as many digits) - (<= (length items) 10)) - ;; Construct a menu of the choices - ;; and then use it for prompting for a single character. - (let* ((overriding-terminal-local-map (make-sparse-keymap)) - (map (make-sparse-keymap title)) - (next-digit ?0) - some-choice-enabled value) - ;; Define SPC as a prefix char to get to this menu. - (define-key overriding-terminal-local-map " " map) - (with-current-buffer (get-buffer-create " widget-choose") - (erase-buffer) - (insert "Available choices:\n\n") - (dolist (choice items) - (when (consp choice) - (let* ((name (car choice)) - (function (cdr choice))) - (insert (format "%c = %s\n" next-digit name)) - (define-key map (vector next-digit) function) - (setq some-choice-enabled t))) - ;; Allocate digits to disabled alternatives - ;; so that the digit of a given alternative never varies. - (incf next-digit)) - (insert "\nC-g = Quit")) - (or some-choice-enabled - (error "None of the choices is currently meaningful")) - (define-key map [?\C-g] 'keyboard-quit) - (define-key map [t] 'keyboard-quit) - ;(setcdr map (nreverse (cdr map))) - ;; Unread a SPC to lead to our new menu. - (push (character-to-event ?\ ) unread-command-events) - ;; Read a char with the menu, and return the result - ;; that corresponds to it. - (save-window-excursion - (display-buffer (get-buffer " widget-choose")) - (let ((cursor-in-echo-area t)) - (setq value - (lookup-key overriding-terminal-local-map - (read-key-sequence (concat title ": ") t))))) - (message "") - (when (or (eq value 'keyboard-quit) - (null value)) - (error "Canceled")) - value)) - (t - ;; Read the choice of name from the minibuffer. - (setq items (remove-if 'stringp items)) - (let ((val (completing-read (concat title ": ") items nil t))) - (if (stringp val) - (let ((try (try-completion val items))) - (when (stringp try) - (setq val try)) - (cdr (assoc val items))) - nil))))) - - -;;; Widget text specifications. -;; -;; These functions are for specifying text properties. - -(defcustom widget-field-add-space t - ;; Setting this to nil might be available, once some problems are resolved. - "Non-nil means add extra space at the end of editable text fields. - -This is needed on all versions of Emacs. If you don't add the space, -it will become impossible to edit a zero size field." - :type 'boolean - :group 'widgets) - -(defcustom widget-field-use-before-change - (and (or (> emacs-minor-version 34) - (> emacs-major-version 19)) - (not (string-match "XEmacs" emacs-version))) - "Non-nil means use `before-change-functions' to track editable fields. -This enables the use of undo, but doesn't work on Emacs 19.34 and earlier. -Using before hooks also means that the :notify function can't know the -new value." - :type 'boolean - :group 'widgets) - -(defun widget-specify-field (widget from to) - "Specify editable button for WIDGET between FROM and TO." - (save-excursion - (goto-char to) - (cond ((null (widget-get widget :size)) - (forward-char 1)) - ;; Terminating space is not part of the field, but necessary in - ;; order for local-map to work. Remove next sexp if local-map works - ;; at the end of the extent. - (widget-field-add-space - (insert-and-inherit " "))) - (setq to (point))) - (let ((map (widget-get widget :keymap)) - (face (or (widget-get widget :value-face) 'widget-field-face)) - (help-echo (widget-get widget :help-echo)) - (extent (make-extent from to))) - (unless (or (stringp help-echo) (null help-echo)) - (setq help-echo 'widget-mouse-help)) - (widget-put widget :field-extent extent) - (and (or (not widget-field-add-space) - (widget-get widget :size)) - (set-extent-property extent 'end-closed t)) - (set-extent-property extent 'detachable nil) - (set-extent-property extent 'field widget) - (set-extent-property extent 'button-or-field t) - (set-extent-property extent 'keymap map) - (set-extent-property extent 'face face) - (set-extent-property extent 'balloon-help help-echo) - (set-extent-property extent 'help-echo help-echo))) - -(defun widget-specify-button (widget from to) - "Specify button for WIDGET between FROM and TO." - (let ((face (widget-apply widget :button-face-get)) - (help-echo (widget-get widget :help-echo)) - (extent (make-extent from to)) - (map (widget-get widget :button-keymap))) - (widget-put widget :button-extent extent) - (unless (or (null help-echo) (stringp help-echo)) - (setq help-echo 'widget-mouse-help)) - (set-extent-property extent 'start-open t) - (set-extent-property extent 'button widget) - (set-extent-property extent 'button-or-field t) - (set-extent-property extent 'mouse-face widget-mouse-face) - (set-extent-property extent 'balloon-help help-echo) - (set-extent-property extent 'help-echo help-echo) - (set-extent-property extent 'face face) - (set-extent-property extent 'keymap map))) - -(defun widget-mouse-help (extent) - "Find mouse help string for button in extent." - (let* ((widget (widget-at (extent-start-position extent))) - (help-echo (and widget (widget-get widget :help-echo)))) - (cond ((stringp help-echo) - help-echo) - ((and (functionp help-echo) - (stringp (setq help-echo (funcall help-echo widget)))) - help-echo) - (t - (format "(widget %S :help-echo %S)" widget help-echo))))) - -(defun widget-specify-sample (widget from to) - ;; Specify sample for WIDGET between FROM and TO. - (let ((face (widget-apply widget :sample-face-get)) - (extent (make-extent from to nil))) - (set-extent-property extent 'start-open t) - (set-extent-property extent 'face face) - (widget-put widget :sample-extent extent))) - -(defun widget-specify-doc (widget from to) - ;; Specify documentation for WIDGET between FROM and TO. - (let ((extent (make-extent from to))) - (set-extent-property extent 'start-open t) - (set-extent-property extent 'widget-doc widget) - (set-extent-property extent 'face widget-documentation-face) - (widget-put widget :doc-extent extent))) - -(defmacro widget-specify-insert (&rest form) - ;; Execute FORM without inheriting any text properties. - `(save-restriction - (let ((inhibit-read-only t) - before-change-functions - after-change-functions) - (insert "<>") - (narrow-to-region (- (point) 2) (point)) - (goto-char (1+ (point-min))) - ;; We use `prog1' instead of a `result' variable, as the latter - ;; confuses the byte-compiler in some cases (a warning). - (prog1 (progn ,@form) - (delete-region (point-min) (1+ (point-min))) - (delete-region (1- (point-max)) (point-max)) - (goto-char (point-max)))))) - -(put 'widget-specify-insert 'edebug-form-spec '(&rest form)) - - -;;; Inactive Widgets. - -(defface widget-inactive-face '((((class grayscale color) - (background dark)) - (:foreground "light gray")) - (((class grayscale color) - (background light)) - (:foreground "dim gray")) - (t - (:italic t))) - "Face used for inactive widgets." - :group 'widget-faces) - -;; For inactiveness to work on complex structures, it is not -;; sufficient to keep track of whether a button/field/glyph is -;; inactive or not -- we must know how many time it was deactivated -;; (inactiveness level). Successive deactivations of the same button -;; increment its inactive-count, and activations decrement it. When -;; inactive-count reaches 0, the button/field/glyph is reactivated. - -(defun widget-activation-widget-mapper (extent action) - "Activate or deactivate EXTENT's widget (button or field). -Suitable for use with `map-extents'." - (ecase action - (:activate - (decf (extent-property extent :inactive-count)) - (when (zerop (extent-property extent :inactive-count)) - (set-extent-properties - extent (extent-property extent :inactive-plist)) - (set-extent-property extent :inactive-plist nil))) - (:deactivate - (incf (extent-property extent :inactive-count 0)) - ;; Store a plist of old properties, which will be fed to - ;; `set-extent-properties'. - (unless (extent-property extent :inactive-plist) - (set-extent-property - extent :inactive-plist - (list 'mouse-face (extent-property extent 'mouse-face) - 'help-echo (extent-property extent 'help-echo) - 'keymap (extent-property extent 'keymap))) - (set-extent-properties - extent '(mouse-face nil help-echo nil keymap nil))))) - nil) - -(defun widget-activation-glyph-mapper (extent action) - (let ((activate-p (if (eq action :activate) t nil))) - (if activate-p - (decf (extent-property extent :inactive-count)) - (incf (extent-property extent :inactive-count 0))) - (when (or (and activate-p - (zerop (extent-property extent :inactive-count))) - (and (not activate-p) - (not (zerop (extent-property extent :inactive-count))))) - (let* ((glyph-widget (extent-property extent 'glyph-widget)) - (up-glyph (widget-get glyph-widget :glyph-up)) - (inactive-glyph (widget-get glyph-widget :glyph-inactive)) - (new-glyph (if activate-p up-glyph inactive-glyph))) - ;; Check that the new glyph exists, and differs from the - ;; default one. - (and up-glyph inactive-glyph (not (eq up-glyph inactive-glyph)) - ;; Check if the glyph is already installed. - (not (eq (extent-end-glyph extent) new-glyph)) - ;; Change it. - (set-extent-end-glyph extent new-glyph))))) - nil) - -(defun widget-specify-inactive (widget from to) - "Make WIDGET inactive for user modifications." - (unless (widget-get widget :inactive) - (let ((extent (make-extent from to))) - ;; It is no longer necessary for the extent to be read-only, as - ;; the inactive editable fields now lose their keymaps. - (set-extent-properties - extent '(start-open t face widget-inactive-face - detachable t priority 2001 widget-inactive t)) - (widget-put widget :inactive extent)) - ;; Deactivate the buttons and fields within the range. In some - ;; cases, the fields are not yet setup at the time this function - ;; is called. Those fields are deactivated explicitly by - ;; `widget-setup'. - (map-extents 'widget-activation-widget-mapper - nil from to :deactivate nil 'button-or-field) - ;; Deactivate glyphs. - (map-extents 'widget-activation-glyph-mapper - nil from to :deactivate nil 'glyph-widget))) - -(defun widget-specify-active (widget) - "Make WIDGET active for user modifications." - (let ((inactive (widget-get widget :inactive))) - (when inactive - ;; Reactivate the buttons and fields covered by the extent. - (map-extents 'widget-activation-widget-mapper - inactive nil nil :activate nil 'button-or-field) - ;; Reactivate the glyphs. - (map-extents 'widget-activation-glyph-mapper - inactive nil nil :activate nil 'end-glyph) - (delete-extent inactive) - (widget-put widget :inactive nil)))) - - -;;; Widget Properties. - -(defsubst widget-type (widget) - "Return the type of WIDGET, a symbol." - (car widget)) - -(when (or (not (fboundp 'widget-put)) - widget-shadow-subrs) - (defun widget-put (widget property value) - "In WIDGET set PROPERTY to VALUE. -The value can later be retrived with `widget-get'." - (setcdr widget (plist-put (cdr widget) property value)))) - -;; Recoded in C, for efficiency: -(when (or (not (fboundp 'widget-get)) - widget-shadow-subrs) - (defun widget-get (widget property) - "In WIDGET, get the value of PROPERTY. -The value could either be specified when the widget was created, or -later with `widget-put'." - (let ((missing t) - value tmp) - (while missing - (cond ((setq tmp (widget-plist-member (cdr widget) property)) - (setq value (car (cdr tmp)) - missing nil)) - ((setq tmp (car widget)) - (setq widget (get tmp 'widget-type))) - (t - (setq missing nil)))) - value))) - -(defun widget-get-indirect (widget property) - "In WIDGET, get the value of PROPERTY. -If the value is a symbol, return its binding. -Otherwise, just return the value." - (let ((value (widget-get widget property))) - (if (symbolp value) - (symbol-value value) - value))) - -(defun widget-member (widget property) - "Non-nil iff there is a definition in WIDGET for PROPERTY." - (cond ((widget-plist-member (cdr widget) property) - t) - ((car widget) - (widget-member (get (car widget) 'widget-type) property)) - (t nil))) - -(when (or (not (fboundp 'widget-apply)) - widget-shadow-subrs) - ;;This is in C, so don't ###utoload - (defun widget-apply (widget property &rest args) - "Apply the value of WIDGET's PROPERTY to the widget itself. -ARGS are passed as extra arguments to the function." - (apply (widget-get widget property) widget args))) - -(defun widget-value (widget) - "Extract the current value of WIDGET." - (widget-apply widget - :value-to-external (widget-apply widget :value-get))) - -(defun widget-value-set (widget value) - "Set the current value of WIDGET to VALUE." - (widget-apply widget - :value-set (widget-apply widget - :value-to-internal value))) - -(defun widget-match-inline (widget vals) - ;; In WIDGET, match the start of VALS. - (cond ((widget-get widget :inline) - (widget-apply widget :match-inline vals)) - ((and vals - (widget-apply widget :match (car vals))) - (cons (list (car vals)) (cdr vals))) - (t nil))) - -(defun widget-apply-action (widget &optional event) - "Apply :action in WIDGET in response to EVENT." - (if (widget-apply widget :active) - (widget-apply widget :action event) - (error "Attempt to perform action on inactive widget"))) - - -;;; Helper functions. -;; -;; These are widget specific. - -;;;###autoload -(defun widget-prompt-value (widget prompt &optional value unbound) - "Prompt for a value matching WIDGET, using PROMPT. -The current value is assumed to be VALUE, unless UNBOUND is non-nil." - (unless (listp widget) - (setq widget (list widget))) - (setq prompt (format "[%s] %s" (widget-type widget) prompt)) - (setq widget (widget-convert widget)) - (let ((answer (widget-apply widget :prompt-value prompt value unbound))) - (unless (widget-apply widget :match answer) - (error "Value does not match %S type." (car widget))) - answer)) - -(defun widget-get-sibling (widget) - "Get the item WIDGET is assumed to toggle. -This is only meaningful for radio buttons or checkboxes in a list." - (let* ((parent (widget-get widget :parent)) - (children (widget-get parent :children)) - child) - (catch 'child - (while children - (setq child (car children) - children (cdr children)) - (when (eq (widget-get child :button) widget) - (throw 'child child))) - nil))) - -(defun widget-map-buttons (function &optional buffer maparg) - "Map FUNCTION over the buttons in BUFFER. -FUNCTION is called with the arguments WIDGET and MAPARG. - -If FUNCTION returns non-nil, the walk is cancelled. - -The arguments MAPARG, and BUFFER default to nil and (current-buffer), -respectively." - (map-extents (lambda (extent ignore) - ;; If FUNCTION returns non-nil, we bail out - (funcall function (extent-property extent 'button) maparg)) - nil nil nil nil nil - 'button)) - - -;;; Glyphs. - -(defcustom widget-glyph-directory (locate-data-directory "custom") - "Where widget glyphs are located. -If this variable is nil, widget will try to locate the directory -automatically." - :group 'widgets - :type 'directory) - -(defcustom widget-glyph-enable t - "If non nil, use glyphs in images when available." - :group 'widgets - :type 'boolean) - -(defcustom widget-image-conversion - '((xpm ".xpm") (gif ".gif") (png ".png") (jpeg ".jpg" ".jpeg") - (xbm ".xbm")) - "Conversion alist from image formats to file name suffixes." - :group 'widgets - :type '(repeat (cons :format "%v" - (symbol :tag "Image Format" unknown) - (repeat :tag "Suffixes" - (string :format "%v"))))) - -(defvar widget-glyph-cache nil - "Cache of glyphs associated with strings (files).") - -(defun widget-glyph-find (image tag) - "Create a glyph corresponding to IMAGE with string TAG as fallback. -IMAGE can already be a glyph, or a file name sans extension (xpm, - xbm, gif, jpg, or png) located in `widget-glyph-directory', or - in one of the data directories. -It can also be a valid image instantiator, in which case it will be - used to make the glyph, with an additional TAG string fallback." - (cond ((not (and image widget-glyph-enable - ;; We don't use glyphs on TTY consoles, although we - ;; could. However, glyph faces aren't yet working - ;; properly, and movement through glyphs is - ;; unintuitive. - (console-on-window-system-p))) - ;; We don't want to use glyphs. - nil) - ((glyphp image) - ;; Already a glyph. Use it. - image) - ((stringp image) - ;; A string. Look it up in the cache first... - (or (lax-plist-get widget-glyph-cache image) - ;; ...and then in the relevant directories - (let* ((dirlist (cons (or widget-glyph-directory - (locate-data-directory "custom")) - data-directory-list)) - (formats widget-image-conversion) - file) - (while (and formats (not file)) - ;; This dance is necessary, because XEmacs signals an - ;; error when it encounters an unrecognized image - ;; format. - (when (valid-image-instantiator-format-p (caar formats)) - (setq file (locate-file image dirlist - (mapconcat 'identity (cdar formats) - ":")))) - (unless file - (pop formats))) - (when file - ;; We create a glyph with the file as the default image - ;; instantiator, and the TAG fallback - (let ((glyph (make-glyph `([,(caar formats) :file ,file] - [string :data ,tag])))) - ;; Cache the glyph - (laxputf widget-glyph-cache image glyph) - ;; ...and return it - glyph))))) - ((valid-instantiator-p image 'image) - ;; A valid image instantiator (e.g. [gif :file "somefile"] etc.) - (make-glyph `(,image [string :data ,tag]))) - (t - ;; Oh well. - nil))) - -(defun widget-glyph-insert (widget tag image &optional down inactive) - "In WIDGET, insert the text TAG or, if supported, IMAGE. -IMAGE should either be a glyph, an image instantiator, an image file -name sans extension (xpm, xbm, gif, jpg, or png) located in -`widget-glyph-directory', or anything else allowed by -`widget-glyph-find'. - -If IMAGE is a list, it will be taken as a list of (UP DOWN INACTIVE) -glyphs. The down and inactive glyphs are shown when glyph is pressed -or inactive, respectively. - -The optional DOWN and INACTIVE arguments are deprecated, and exist -only because of compatibility." - ;; Convert between IMAGE being a list, etc. Must use `psetq', - ;; because otherwise change to `image' screws up the rest. - (psetq image (or (and (consp image) - (car image)) - image) - down (or (and (consp image) - (nth 1 image)) - down) - inactive (or (and (consp image) - (nth 2 image)) - inactive)) - (let ((glyph (widget-glyph-find image tag))) - (if glyph - (widget-glyph-insert-glyph widget glyph - (widget-glyph-find down tag) - (widget-glyph-find inactive tag)) - (insert tag)) - glyph)) - -(defun widget-glyph-insert-glyph (widget glyph &optional down inactive) - "In WIDGET, insert GLYPH. -If optional arguments DOWN and INACTIVE are given, they should be -glyphs used when the widget is pushed and inactive, respectively." - (insert "*") - (let ((extent (make-extent (point) (1- (point)))) - (help-echo (and widget (widget-get widget :help-echo))) - (map (and widget (widget-get widget :button-keymap)))) - (set-extent-property extent 'glyph-widget widget) - ;; It would be fun if we could make this extent atomic, so it - ;; doesn't mess with cursor motion. But atomic-extents library is - ;; currently a mess, so I'd rather not use it. - (set-extent-property extent 'invisible t) - (set-extent-property extent 'start-open t) - (set-extent-property extent 'end-open t) - (set-extent-property extent 'keymap map) - (set-extent-end-glyph extent glyph) - (unless (or (stringp help-echo) (null help-echo)) - (setq help-echo 'widget-mouse-help)) - (when help-echo - (set-extent-property extent 'balloon-help help-echo) - (set-extent-property extent 'help-echo help-echo))) - (when widget - (widget-put widget :glyph-up glyph) - (when down (widget-put widget :glyph-down down)) - (when inactive (widget-put widget :glyph-inactive inactive)))) - - -;;; Buttons. - -(defgroup widget-button nil - "The look of various kinds of buttons." - :group 'widgets) - -(defcustom widget-button-prefix "" - "String used as prefix for buttons." - :type 'string - :group 'widget-button) - -(defcustom widget-button-suffix "" - "String used as suffix for buttons." - :type 'string - :group 'widget-button) - - -;;; Creating Widgets. - -;;;###autoload -(defun widget-create (type &rest args) - "Create widget of TYPE. -The optional ARGS are additional keyword arguments." - (let ((widget (apply 'widget-convert type args))) - (widget-apply widget :create) - widget)) - -(defun widget-create-child-and-convert (parent type &rest args) - "As part of the widget PARENT, create a child widget TYPE. -The child is converted, using the keyword arguments ARGS." - (let ((widget (apply 'widget-convert type args))) - (widget-put widget :parent parent) - (unless (widget-get widget :indent) - (widget-put widget :indent (+ (or (widget-get parent :indent) 0) - (or (widget-get widget :extra-offset) 0) - (widget-get parent :offset)))) - (widget-apply widget :create) - widget)) - -(defun widget-create-child (parent type) - "Create widget of TYPE." - (let ((widget (copy-sequence type))) - (widget-put widget :parent parent) - (unless (widget-get widget :indent) - (widget-put widget :indent (+ (or (widget-get parent :indent) 0) - (or (widget-get widget :extra-offset) 0) - (widget-get parent :offset)))) - (widget-apply widget :create) - widget)) - -(defun widget-create-child-value (parent type value) - "Create widget of TYPE with value VALUE." - (let ((widget (copy-sequence type))) - (widget-put widget :value (widget-apply widget :value-to-internal value)) - (widget-put widget :parent parent) - (unless (widget-get widget :indent) - (widget-put widget :indent (+ (or (widget-get parent :indent) 0) - (or (widget-get widget :extra-offset) 0) - (widget-get parent :offset)))) - (widget-apply widget :create) - widget)) - -;;;###autoload -(defun widget-delete (widget) - "Delete WIDGET." - (widget-apply widget :delete)) - -(defun widget-convert (type &rest args) - "Convert TYPE to a widget without inserting it in the buffer. -The optional ARGS are additional keyword arguments." - ;; Don't touch the type. - (let* ((widget (if (symbolp type) - (list type) - (copy-sequence type))) - (current widget) - (keys args)) - ;; First set the :args keyword. - (while (cdr current) ;Look in the type. - (let ((next (car (cdr current)))) - (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) - (setq current (cdr (cdr current))) - (setcdr current (list :args (cdr current))) - (setq current nil)))) - (while args ;Look in the args. - (let ((next (nth 0 args))) - (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) - (setq args (nthcdr 2 args)) - (widget-put widget :args args) - (setq args nil)))) - ;; Then Convert the widget. - (setq type widget) - (while type - (let ((convert-widget (plist-get (cdr type) :convert-widget))) - (if convert-widget - (setq widget (funcall convert-widget widget)))) - (setq type (get (car type) 'widget-type))) - ;; Finally set the keyword args. - (while keys - (let ((next (nth 0 keys))) - (if (and (symbolp next) (eq (aref (symbol-name next) 0) ?:)) - (progn - (widget-put widget next (nth 1 keys)) - (setq keys (nthcdr 2 keys))) - (setq keys nil)))) - ;; Convert the :value to internal format. - (if (widget-member widget :value) - (let ((value (widget-get widget :value))) - (widget-put widget - :value (widget-apply widget :value-to-internal value)))) - ;; Return the newly created widget. - widget)) - -(defun widget-insert (&rest args) - "Call `insert' with ARGS and make the text read only." - (let ((inhibit-read-only t) - before-change-functions - after-change-functions) - (apply 'insert args))) - -(defun widget-convert-text (type from to - &optional button-from button-to - &rest args) - "Return a widget of type TYPE with endpoint FROM TO. -Optional ARGS are extra keyword arguments for TYPE. -and TO will be used as the widgets end points. If optional arguments -BUTTON-FROM and BUTTON-TO are given, these will be used as the widgets -button end points. -Optional ARGS are extra keyword arguments for TYPE." - (let ((widget (apply 'widget-convert type :delete 'widget-leave-text args)) - (from (copy-marker from)) - (to (copy-marker to))) - (set-marker-insertion-type from t) - (set-marker-insertion-type to nil) - (widget-put widget :from from) - (widget-put widget :to to) - (when button-from - (widget-specify-button widget button-from button-to)) - widget)) - -(defun widget-convert-button (type from to &rest args) - "Return a widget of type TYPE with endpoint FROM TO. -Optional ARGS are extra keyword arguments for TYPE. -No text will be inserted to the buffer, instead the text between FROM -and TO will be used as the widgets end points, as well as the widgets -button end points." - (apply 'widget-convert-text type from to from to args)) - -(defun widget-leave-text (widget) - "Remove markers and extents from WIDGET and its children." - (let ((from (widget-get widget :from)) - (to (widget-get widget :to)) - (button (widget-get widget :button-extent)) - (sample (widget-get widget :sample-extent)) - (doc (widget-get widget :doc-extent)) - (field (widget-get widget :field-extent)) - (children (widget-get widget :children))) - (set-marker from nil) - (set-marker to nil) - ;; Maybe we should delete the extents here? As this code doesn't - ;; remove them from widget structures, maybe it's safer to just - ;; detach them. That's what `delete-overlay' did. - (when button - (detach-extent button)) - (when sample - (detach-extent sample)) - (when doc - (detach-extent doc)) - (when field - (detach-extent field)) - (mapc 'widget-leave-text children))) - - -;;; Keymap and Commands. - -(defvar widget-keymap nil - "Keymap containing useful binding for buffers containing widgets. -Recommended as a parent keymap for modes using widgets.") - -(unless widget-keymap - (setq widget-keymap (make-sparse-keymap)) - (define-key widget-keymap [tab] 'widget-forward) - (define-key widget-keymap [(shift tab)] 'widget-backward) - (define-key widget-keymap [(meta tab)] 'widget-backward) - (define-key widget-keymap [backtab] 'widget-backward)) - -(defvar widget-global-map global-map - "Keymap used for events the widget does not handle themselves.") -(make-variable-buffer-local 'widget-global-map) - -(defvar widget-field-keymap nil - "Keymap used inside an editable field.") - -(unless widget-field-keymap - (setq widget-field-keymap (make-sparse-keymap)) - (set-keymap-parents widget-field-keymap global-map) - (define-key widget-field-keymap "\C-k" 'widget-kill-line) - (define-key widget-field-keymap [(meta tab)] 'widget-complete) - (define-key widget-field-keymap [tab] 'widget-forward) - (define-key widget-field-keymap [(shift tab)] 'widget-backward) - (define-key widget-field-keymap "\C-m" 'widget-field-activate) - (define-key widget-field-keymap "\C-a" 'widget-beginning-of-line) - (define-key widget-field-keymap "\C-e" 'widget-end-of-line) - (define-key widget-field-keymap "\C-t" 'widget-transpose-chars)) - -(defvar widget-text-keymap nil - "Keymap used inside a text field.") - -(unless widget-text-keymap - (setq widget-text-keymap (make-sparse-keymap)) - (set-keymap-parents widget-field-keymap global-map) - (define-key widget-text-keymap "\C-a" 'widget-beginning-of-line) - (define-key widget-text-keymap "\C-e" 'widget-end-of-line) - (define-key widget-text-keymap "\C-t" 'widget-transpose-chars)) - -(defvar widget-button-keymap nil - "Keymap used inside a button.") - -(unless widget-button-keymap - (setq widget-button-keymap (make-sparse-keymap)) - (set-keymap-parents widget-button-keymap widget-keymap) - (define-key widget-button-keymap "\C-m" 'widget-button-press) - (define-key widget-button-keymap [button2] 'widget-button-click) - ;; Ideally, button3 within a button should invoke a button-specific - ;; menu. - (define-key widget-button-keymap [button3] 'widget-button-click) - ;;Glyph support. - (define-key widget-button-keymap [button1] 'widget-button1-click)) - - -(defun widget-field-activate (pos &optional event) - "Invoke the ediable field at point." - (interactive "@d") - (let ((field (widget-field-find pos))) - (if field - (widget-apply-action field event) - (call-interactively - (lookup-key widget-global-map (this-command-keys)))))) - -(defface widget-button-pressed-face - '((((class color)) - (:foreground "red")) - (t - (:bold t :underline t))) - "Face used for pressed buttons." - :group 'widget-faces) - -(defun widget-event-point (event) - "Character position of the mouse event, or nil." - (and (mouse-event-p event) - (event-point event))) - -(defun widget-button-click (event) - "Invoke button below mouse pointer." - (interactive "@e") - (cond ((event-glyph event) - (widget-glyph-click event)) - ((widget-event-point event) - (let* ((pos (widget-event-point event)) - (button (get-char-property pos 'button))) - (if button - (let* ((extent (widget-get button :button-extent)) - (face (extent-property extent 'face)) - (mouse-face (extent-property extent 'mouse-face)) - (help-echo (extent-property extent 'help-echo))) - (unwind-protect - (progn - ;; Merge relevant faces, and make the result mouse-face. - (let ((merge `(widget-button-pressed-face ,mouse-face))) - (nconc merge (if (listp face) - face (list face))) - (setq merge (delete-if-not 'find-face merge)) - (set-extent-property extent 'mouse-face merge)) - (unless (widget-apply button :mouse-down-action event) - ;; Wait for button release. - (while (not (button-release-event-p - (setq event (next-event)))) - (dispatch-event event))) - ;; Disallow mouse-face and help-echo. - (set-extent-property extent 'mouse-face nil) - (set-extent-property extent 'help-echo nil) - (setq pos (widget-event-point event)) - (unless (eq (current-buffer) (extent-object extent)) - ;; Barf if dispatch-event tripped us by - ;; changing buffer. - (error "Buffer changed during mouse motion")) - ;; Do the associated action. - (when (and pos (extent-in-region-p extent pos pos)) - (widget-apply-action button event))) - ;; Unwinding: fully release the button. - (set-extent-property extent 'mouse-face mouse-face) - (set-extent-property extent 'help-echo help-echo))) - ;; This should not happen! - (error "`widget-button-click' called outside button")))) - (t - (message "You clicked somewhere weird")))) - -(defun widget-button1-click (event) - "Invoke glyph below mouse pointer." - (interactive "@e") - (if (event-glyph event) - (widget-glyph-click event) - ;; Should somehow avoid this. - (let ((command (lookup-key widget-global-map (this-command-keys)))) - (and (commandp command) - (call-interactively command))))) - -(defun widget-glyph-click (event) - "Handle click on a glyph." - (let* ((glyph (event-glyph event)) - (extent (event-glyph-extent event)) - (widget (extent-property extent 'glyph-widget)) - (down-glyph (or (and widget (widget-get widget :glyph-down)) glyph)) - (up-glyph (or (and widget (widget-get widget :glyph-up)) glyph)) - (last event)) - (unless (widget-apply widget :active) - (error "This widget is inactive")) - (let ((current-glyph 'down)) - ;; We always know what glyph is drawn currently, to avoid - ;; unnecessary extent changes. Is this any noticable gain? - (unwind-protect - (progn - ;; Press the glyph. - (set-extent-end-glyph extent down-glyph) - ;; Redisplay (shouldn't be needed, but...) - (sit-for 0) - (unless (widget-apply widget :mouse-down-action event) - ;; Wait for the release. - (while (not (button-release-event-p last)) - (unless (button-press-event-p last) - (dispatch-event last)) - (when (motion-event-p last) - ;; Update glyphs on mouse motion. - (if (eq extent (event-glyph-extent last)) - (unless (eq current-glyph 'down) - (set-extent-end-glyph extent down-glyph) - (setq current-glyph 'down)) - (unless (eq current-glyph 'up) - (set-extent-end-glyph extent up-glyph) - (setq current-glyph 'up)))) - (setq last (next-event event)))) - (unless (eq (current-buffer) (extent-object extent)) - ;; Barf if dispatch-event tripped us by changing buffer. - (error "Buffer changed during mouse motion")) - ;; Apply widget action. - (when (eq extent (event-glyph-extent last)) - (let ((widget (extent-property (event-glyph-extent event) - 'glyph-widget))) - (cond ((null widget) - (message "You clicked on a glyph")) - ((not (widget-apply widget :active)) - (error "This glyph is inactive")) - (t - (widget-apply-action widget event)))))) - ;; Release the glyph. - (and (eq current-glyph 'down) - ;; The extent might have been detached or deleted - (extent-live-p extent) - (not (extent-detached-p extent)) - (set-extent-end-glyph extent up-glyph)))))) - -(defun widget-button-press (pos &optional event) - "Invoke button at POS." - (interactive "@d") - (let ((button (get-char-property pos 'button))) - (if button - (widget-apply-action button event) - (let ((command (lookup-key widget-global-map (this-command-keys)))) - (when (commandp command) - (call-interactively command)))))) - -(defun widget-tabable-at (&optional pos last-tab backwardp) - "Return the tabable widget at POS, or nil. -POS defaults to the value of (point)." - (unless pos - (setq pos (point))) - (let ((widget (widget-at pos))) - (if widget - (let ((order (widget-get widget :tab-order))) - (if order - (if last-tab (and (= order (if backwardp - (1- last-tab) - (1+ last-tab))) - widget) - (and (> order 0) widget)) - widget)) - nil))) - -;; Return the button or field extent at point. -(defun widget-button-or-field-extent (pos) - (or (and (get-char-property pos 'button) - (widget-get (get-char-property pos 'button) - :button-extent)) - (and (get-char-property pos 'field) - (widget-get (get-char-property pos 'field) - :field-extent)))) - -(defun widget-next-button-or-field (pos) - "Find the next button, or field, and return its start position, or nil. -Internal function, don't use it outside `wid-edit'." - (let* ((at-point (widget-button-or-field-extent pos)) - (extent (map-extents - (lambda (ext ignore) - ext) - nil (if at-point (extent-end-position at-point) pos) - nil nil 'start-open 'button-or-field))) - (and extent - (extent-start-position extent)))) - -;; This is too slow in buffers with many buttons (W3). -(defun widget-previous-button-or-field (pos) - "Find the previous button, or field, and return its start position, or nil. -Internal function, don't use it outside `wid-edit'." - (let* ((at-point (widget-button-or-field-extent pos)) - previous-extent) - (map-extents - (lambda (ext ignore) - (if (eq ext at-point) - ;; We reached the extent we were on originally - (if (= pos (extent-start-position at-point)) - previous-extent - (setq previous-extent at-point)) - (setq previous-extent ext) - nil)) - nil nil pos nil 'start-open 'button-or-field) - (and previous-extent - (extent-start-position previous-extent)))) - -(defun widget-move (arg) - "Move point to the ARG next field or button. -ARG may be negative to move backward." - (let ((opoint (point)) (wrapped 0) - (last-tab (widget-get (widget-at (point)) :tab-order)) - nextpos found) - ;; Movement backward - (while (< arg 0) - (setq nextpos (widget-previous-button-or-field (point))) - (if nextpos - (progn - (goto-char nextpos) - (when (and (not (get-char-property nextpos 'widget-inactive)) - (widget-tabable-at nil last-tab t)) - (incf arg) - (setq found t - last-tab (widget-get (widget-at (point)) - :tab-order)))) - (if (and (not found) (> wrapped 1)) - (setq arg 0 - found nil) - (goto-char (point-max)) - (incf wrapped)))) - ;; Movement forward - (while (> arg 0) - (setq nextpos (widget-next-button-or-field (point))) - (if nextpos - (progn - (goto-char nextpos) - (when (and (not (get-char-property nextpos 'widget-inactive)) - (widget-tabable-at nil last-tab)) - (decf arg) - (setq found t - last-tab (widget-get (widget-at (point)) - :tab-order)))) - (if (and (not found) (> wrapped 1)) - (setq arg 0 - found nil) - (goto-char (point-min)) - (incf wrapped)))) - (if (not found) - (goto-char opoint) - (widget-echo-help (point)) - (run-hooks 'widget-move-hook)))) - -(defun widget-forward (arg) - "Move point to the next field or button. -With optional ARG, move across that many fields." - (interactive "p") - (run-hooks 'widget-forward-hook) - (widget-move arg)) - -(defun widget-backward (arg) - "Move point to the previous field or button. -With optional ARG, move across that many fields." - (interactive "p") - (run-hooks 'widget-backward-hook) - (widget-move (- arg))) - -(defun widget-beginning-of-line () - "Go to beginning of field or beginning of line, whichever is first." - (interactive "_") - (let* ((field (widget-field-find (point))) - (start (and field (widget-field-start field)))) - (if (and start (not (eq start (point)))) - (goto-char start) - (call-interactively 'beginning-of-line)))) - -(defun widget-end-of-line () - "Go to end of field or end of line, whichever is first." - (interactive "_") - (let* ((field (widget-field-find (point))) - (end (and field (widget-field-end field)))) - (if (and end (not (eq end (point)))) - (goto-char end) - (call-interactively 'end-of-line)))) - -(defun widget-kill-line () - "Kill to end of field or end of line, whichever is first." - (interactive) - (let* ((field (widget-field-find (point))) - (newline (save-excursion (forward-line 1) (point))) - (end (and field (widget-field-end field)))) - (if (and field (> newline end)) - (kill-region (point) end) - (call-interactively 'kill-line)))) - -(defun widget-transpose-chars (arg) - "Like `transpose-chars', but works correctly at end of widget." - (interactive "*P") - (let* ((field (widget-field-find (point))) - (start (and field (widget-field-start field))) - (end (and field (widget-field-end field))) - (last-non-space (and start end - (save-excursion - (goto-char end) - (skip-chars-backward " \t\n" start) - (point))))) - (cond ((and last-non-space - (or (= last-non-space start) - (= last-non-space (1+ start)))) - ;; empty or one-character field - nil) - ((= (point) start) - ;; at the beginning of the field -- we would get an error here. - (error "Cannot transpose at beginning of field")) - (t - (when (and (null arg) - (= last-non-space (point))) - (forward-char -1)) - (transpose-chars arg))))) - -(defcustom widget-complete-field (lookup-key global-map "\M-\t") - "Default function to call for completion inside fields." - :options '(ispell-complete-word complete-tag lisp-complete-symbol) - :type 'function - :group 'widgets) - -(defun widget-complete () - "Complete content of editable field from point. -When not inside a field, move to the previous button or field." - (interactive) - (let ((field (widget-field-find (point)))) - (if field - (widget-apply field :complete) - (error "Not in an editable field")))) - - -;;; Setting up the buffer. - -(defvar widget-field-new nil) -;; List of all newly created editable fields in the buffer. -(make-variable-buffer-local 'widget-field-new) - -(defvar widget-field-list nil) -;; List of all editable fields in the buffer. -(make-variable-buffer-local 'widget-field-list) - -(defun widget-setup () - "Setup current buffer so editing string widgets works." - (let ((inhibit-read-only t) - (after-change-functions nil) - before-change-functions - field) - (while widget-field-new - (setq field (car widget-field-new) - widget-field-new (cdr widget-field-new) - widget-field-list (cons field widget-field-list)) - (let ((from (car (widget-get field :field-extent))) - (to (cdr (widget-get field :field-extent)))) - (widget-specify-field field - (marker-position from) (marker-position to)) - (set-marker from nil) - (set-marker to nil)) - ;; If the field is placed within the inactive zone, deactivate it. - (let ((extent (widget-get field :field-extent))) - (when (get-char-property (extent-start-position extent) - 'widget-inactive) - (widget-activation-widget-mapper extent :deactivate))))) - (widget-clear-undo) - (widget-add-change)) - -(defvar widget-field-last nil) -;; Last field containing point. -(make-variable-buffer-local 'widget-field-last) - -(defvar widget-field-was nil) -;; The widget data before the change. -(make-variable-buffer-local 'widget-field-was) - -(defun widget-field-buffer (widget) - "Return the start of WIDGET's editing field." - (let ((extent (widget-get widget :field-extent))) - (and extent (extent-object extent)))) - -(defun widget-field-start (widget) - "Return the start of WIDGET's editing field." - (let ((extent (widget-get widget :field-extent))) - (and extent (extent-start-position extent)))) - -(defun widget-field-end (widget) - "Return the end of WIDGET's editing field." - (let ((extent (widget-get widget :field-extent))) - ;; Don't subtract one if local-map works at the end of the extent. - (and extent (if (or widget-field-add-space - (null (widget-get widget :size))) - (1- (extent-end-position extent)) - (extent-end-position extent))))) - -(defun widget-field-find (pos) - "Return the field at POS. -Unlike (get-char-property POS 'field) this, works with empty fields too." - (let ((field-extent (map-extents (lambda (extent ignore) - extent) - nil pos pos nil nil 'field))) - (and field-extent - (extent-property field-extent 'field)))) - -;; Old version, without `map-extents'. -;(defun widget-field-find (pos) -; (let ((fields widget-field-list) -; field found) -; (while fields -; (setq field (car fields) -; fields (cdr fields)) -; (let ((start (widget-field-start field)) -; (end (widget-field-end field))) -; (when (and (<= start pos) (<= pos end)) -; (when found -; (debug "Overlapping fields")) -; (setq found field)))) -; found)) - -(defun widget-before-change (from to) - ;; Barf if the text changed is outside the editable fields. - (unless inhibit-read-only - (let ((from-field (widget-field-find from)) - (to-field (widget-field-find to))) - (cond ((or (null from-field) - (null to-field)) - ;; Either end of change is not within a field. - (add-hook 'post-command-hook 'widget-add-change nil t) - (error "Attempt to change text outside editable field")) - ((not (eq from-field to-field)) - ;; The change begins in one fields, and ends in another one. - (add-hook 'post-command-hook 'widget-add-change nil t) - (error "Change should be restricted to a single field")) - (widget-field-use-before-change - ;; #### Bletch! This loses because XEmacs get confused - ;; if before-change-functions change the contents of - ;; buffer before from/to. - (condition-case nil - (widget-apply from-field :notify from-field) - (error (debug "Before Change")))))))) - -(defun widget-add-change () - (make-local-hook 'post-command-hook) - (remove-hook 'post-command-hook 'widget-add-change t) - (make-local-hook 'before-change-functions) - (add-hook 'before-change-functions 'widget-before-change nil t) - (make-local-hook 'after-change-functions) - (add-hook 'after-change-functions 'widget-after-change nil t)) - -(defun widget-after-change (from to old) - ;; Adjust field size and text properties. - - ;; Also, notify the widgets (so, for example, a variable changes its - ;; state to `modified'. when it is being edited.) - (condition-case nil - (let ((field (widget-field-find from)) - (other (widget-field-find to))) - (when field - (unless (eq field other) - (debug "Change in different fields")) - (let ((size (widget-get field :size)) - (secret (widget-get field :secret))) - (when size - (let ((begin (widget-field-start field)) - (end (widget-field-end field))) - (cond ((< (- end begin) size) - ;; Field too small. - (save-excursion - (goto-char end) - (insert-char ?\ (- (+ begin size) end)))) - ((> (- end begin) size) - ;; Field too large and - (if (or (< (point) (+ begin size)) - (> (point) end)) - ;; Point is outside extra space. - (setq begin (+ begin size)) - ;; Point is within the extra space. - (setq begin (point))) - (save-excursion - (goto-char end) - (while (and (eq (preceding-char) ?\ ) - (> (point) begin)) - (delete-backward-char 1))))))) - (when secret - (let ((begin (widget-field-start field)) - (end (widget-field-end field))) - (when size - (while (and (> end begin) - (eq (char-after (1- end)) ?\ )) - (setq end (1- end)))) - (while (< begin end) - (let ((old (char-after begin))) - (unless (eq old secret) - (subst-char-in-region begin (1+ begin) old secret) - (put-text-property begin (1+ begin) 'secret old)) - (incf begin)))))) - (widget-apply field :notify field))) - (error (debug "After Change")))) - - -;;; Widget Functions -;; -;; These functions are used in the definition of multiple widgets. - -(defun widget-parent-action (widget &optional event) - "Tell :parent of WIDGET to handle the :action. -Optional EVENT is the event that triggered the action." - (widget-apply (widget-get widget :parent) :action event)) - -(defun widget-children-value-delete (widget) - "Delete all :children and :buttons in WIDGET." - (mapc 'widget-delete (widget-get widget :children)) - (widget-put widget :children nil) - (mapc 'widget-delete (widget-get widget :buttons)) - (widget-put widget :buttons nil)) - -(defun widget-children-validate (widget) - "All the :children must be valid." - (let ((children (widget-get widget :children)) - child found) - (while (and children (not found)) - (setq child (car children) - children (cdr children) - found (widget-apply child :validate))) - found)) - -(defun widget-types-convert-widget (widget) - "Convert :args as widget types in WIDGET." - (widget-put widget :args (mapcar 'widget-convert (widget-get widget :args))) - widget) - -(defun widget-value-convert-widget (widget) - "Initialize :value from :args in WIDGET." - (let ((args (widget-get widget :args))) - (when args - (widget-put widget :value (car args)) - ;; Don't convert :value here, as this is done in `widget-convert'. - ;; (widget-put widget :value (widget-apply widget - ;; :value-to-internal (car args))) - (widget-put widget :args nil))) - widget) - -(defun widget-value-value-get (widget) - "Return the :value property of WIDGET." - (widget-get widget :value)) - -;;; The `default' Widget. - -(define-widget 'default nil - "Basic widget other widgets are derived from." - :value-to-internal (lambda (widget value) value) - :value-to-external (lambda (widget value) value) - :button-prefix 'widget-button-prefix - :button-suffix 'widget-button-suffix - :complete 'widget-default-complete - :create 'widget-default-create - :indent nil - :offset 0 - :format-handler 'widget-default-format-handler - :button-face-get 'widget-default-button-face-get - :sample-face-get 'widget-default-sample-face-get - :button-keymap widget-button-keymap - :delete 'widget-default-delete - :value-set 'widget-default-value-set - :value-inline 'widget-default-value-inline - :menu-tag-get 'widget-default-menu-tag-get - :validate (lambda (widget) nil) - :active 'widget-default-active - :activate 'widget-specify-active - :deactivate 'widget-default-deactivate - :mouse-down-action (lambda (widget event) nil) - :action 'widget-default-action - :notify 'widget-default-notify - :prompt-value 'widget-default-prompt-value) - -(defun widget-default-complete (widget) - "Call the value of the :complete-function property of WIDGET. -If that does not exists, call the value of `widget-complete-field'." - (let ((fun (widget-get widget :complete-function))) - (call-interactively (or fun widget-complete-field)))) - -(defun widget-default-create (widget) - "Create WIDGET at point in the current buffer." - (widget-specify-insert - (let ((from (point)) - button-begin button-end button-glyph - sample-begin sample-end - doc-begin doc-end - value-pos) - (insert (widget-get widget :format)) - (goto-char from) - ;; Parse escapes in format. Coding this in C would speed up - ;; things *a lot*. - (while (re-search-forward "%\\(.\\)" nil t) - (let ((escape (aref (match-string 1) 0))) - (replace-match "" t t) - (cond ((eq escape ?%) - (insert "%")) - ((eq escape ?\[) - (setq button-begin (point-marker)) - (set-marker-insertion-type button-begin nil)) - ((eq escape ?\]) - (setq button-end (point-marker)) - (set-marker-insertion-type button-end nil)) - ((eq escape ?\{) - (setq sample-begin (point))) - ((eq escape ?\}) - (setq sample-end (point))) - ((eq escape ?n) - (when (widget-get widget :indent) - (insert "\n") - (insert-char ?\ (widget-get widget :indent)))) - ((eq escape ?t) - (let* ((tag (widget-get widget :tag)) - (glyph (widget-get widget :tag-glyph))) - (cond (glyph - (setq button-glyph - (widget-glyph-insert - widget (or tag "Image") glyph))) - (tag - (insert tag)) - (t - (let ((standard-output (current-buffer))) - (princ (widget-get widget :value))))))) - ((eq escape ?d) - (let ((doc (widget-get widget :doc))) - (when doc - (setq doc-begin (point)) - (insert doc) - (while (eq (preceding-char) ?\n) - (delete-backward-char 1)) - (insert "\n") - (setq doc-end (point))))) - ((eq escape ?v) - (if (and button-begin (not button-end)) - (widget-apply widget :value-create) - (setq value-pos (point-marker)))) - (t - (widget-apply widget :format-handler escape))))) - ;; Specify button, sample, and doc, and insert value. - (when (and button-begin button-end) - (unless button-glyph - (goto-char button-begin) - (insert (widget-get-indirect widget :button-prefix)) - (goto-char button-end) - (set-marker-insertion-type button-end t) - (insert (widget-get-indirect widget :button-suffix))) - (widget-specify-button widget button-begin button-end) - ;; Is this necessary? - (set-marker button-begin nil) - (set-marker button-end nil)) - (and sample-begin sample-end - (widget-specify-sample widget sample-begin sample-end)) - (and doc-begin doc-end - (widget-specify-doc widget doc-begin doc-end)) - (when value-pos - (goto-char value-pos) - (widget-apply widget :value-create))) - (let ((from (point-min-marker)) - (to (point-max-marker))) - (set-marker-insertion-type from t) - (set-marker-insertion-type to nil) - (widget-put widget :from from) - (widget-put widget :to to))) - (widget-clear-undo)) - -(defun widget-default-format-handler (widget escape) - ;; We recognize the %h escape by default. - (let* ((buttons (widget-get widget :buttons))) - (cond ((eq escape ?h) - (let* ((doc-property (widget-get widget :documentation-property)) - (doc-try (cond ((widget-get widget :doc)) - ((symbolp doc-property) - (documentation-property - (widget-get widget :value) - doc-property)) - (t - (funcall doc-property - (widget-get widget :value))))) - (doc-text (and (stringp doc-try) - (> (length doc-try) 1) - doc-try)) - (doc-indent (widget-get widget :documentation-indent))) - (when doc-text - (and (eq (preceding-char) ?\n) - (widget-get widget :indent) - (insert-char ?\ (widget-get widget :indent))) - ;; The `*' in the beginning is redundant. - (when (eq (aref doc-text 0) ?*) - (setq doc-text (substring doc-text 1))) - ;; Get rid of trailing newlines. - (when (string-match "\n+\\'" doc-text) - (setq doc-text (substring doc-text 0 (match-beginning 0)))) - (push (widget-create-child-and-convert - widget 'documentation-string - :indent (cond ((numberp doc-indent) - doc-indent) - ((null doc-indent) - nil) - (t 0)) - doc-text) - buttons)))) - (t - (error "Unknown escape `%c'" escape))) - (widget-put widget :buttons buttons))) - -(defun widget-default-button-face-get (widget) - ;; Use :button-face or widget-button-face - (or (widget-get widget :button-face) - (let ((parent (widget-get widget :parent))) - (if parent - (widget-apply parent :button-face-get) - widget-button-face)))) - -(defun widget-default-sample-face-get (widget) - ;; Use :sample-face. - (widget-get widget :sample-face)) - -(defun widget-default-delete (widget) - ;; Remove widget from the buffer. - (let ((from (widget-get widget :from)) - (to (widget-get widget :to)) - (inactive-extent (widget-get widget :inactive)) - (button-extent (widget-get widget :button-extent)) - (sample-extent (widget-get widget :sample-extent)) - (doc-extent (widget-get widget :doc-extent)) - before-change-functions - after-change-functions - (inhibit-read-only t)) - (widget-apply widget :value-delete) - (when inactive-extent - (detach-extent inactive-extent)) - (when button-extent - (detach-extent button-extent)) - (when sample-extent - (detach-extent sample-extent)) - (when doc-extent - (detach-extent doc-extent)) - (when (< from to) - ;; Kludge: this doesn't need to be true for empty formats. - (delete-region from to)) - (set-marker from nil) - (set-marker to nil)) - (widget-clear-undo)) - -(defun widget-default-value-set (widget value) - ;; Recreate widget with new value. - (let* ((old-pos (point)) - (from (copy-marker (widget-get widget :from))) - (to (copy-marker (widget-get widget :to))) - (offset (if (and (<= from old-pos) (<= old-pos to)) - (if (>= old-pos (1- to)) - (- old-pos to 1) - (- old-pos from))))) - ;;??? Bug: this ought to insert the new value before deleting the old one, - ;; so that markers on either side of the value automatically - ;; stay on the same side. -- rms. - (save-excursion - (goto-char (widget-get widget :from)) - (widget-apply widget :delete) - (widget-put widget :value value) - (widget-apply widget :create)) - (when offset - (if (< offset 0) - (goto-char (+ (widget-get widget :to) offset 1)) - (goto-char (min (+ from offset) (1- (widget-get widget :to)))))))) - -(defun widget-default-value-inline (widget) - ;; Wrap value in a list unless it is inline. - (if (widget-get widget :inline) - (widget-value widget) - (list (widget-value widget)))) - -(defun widget-default-menu-tag-get (widget) - ;; Use tag or value for menus. - (or (widget-get widget :menu-tag) - (widget-get widget :tag) - (widget-princ-to-string (widget-get widget :value)))) - -(defun widget-default-active (widget) - "Return t iff this widget active (user modifiable)." - (and (not (widget-get widget :inactive)) - (let ((parent (widget-get widget :parent))) - (or (null parent) - (widget-apply parent :active))))) - -(defun widget-default-deactivate (widget) - "Make WIDGET inactive for user modifications." - (widget-specify-inactive widget - (widget-get widget :from) - (widget-get widget :to))) - -(defun widget-default-action (widget &optional event) - ;; Notify the parent when a widget change - (let ((parent (widget-get widget :parent))) - (when parent - (widget-apply parent :notify widget event)))) - -(defun widget-default-notify (widget child &optional event) - ;; Pass notification to parent. - (widget-default-action widget event)) - -(defun widget-default-prompt-value (widget prompt value unbound) - ;; Read an arbitrary value. Stolen from `set-variable'. -;; (let ((initial (if unbound -;; nil -;; ;; It would be nice if we could do a `(cons val 1)' here. -;; (prin1-to-string (custom-quote value)))))) - (eval-minibuffer prompt )) - -;;; The `item' Widget. - -(define-widget 'item 'default - "Constant items for inclusion in other widgets." - :convert-widget 'widget-value-convert-widget - :value-create 'widget-item-value-create - :value-delete 'ignore - :value-get 'widget-value-value-get - :match 'widget-item-match - :match-inline 'widget-item-match-inline - :action 'widget-item-action - :format "%t\n") - -(defun widget-item-value-create (widget) - ;; Insert the printed representation of the value. - (let ((standard-output (current-buffer))) - (princ (widget-get widget :value)))) - -(defun widget-item-match (widget value) - ;; Match if the value is the same. - (equal (widget-get widget :value) value)) - -(defun widget-item-match-inline (widget values) - ;; Match if the value is the same. - (let ((value (widget-get widget :value))) - (and (listp value) - (<= (length value) (length values)) - (let ((head (widget-sublist values 0 (length value)))) - (and (equal head value) - (cons head (widget-sublist values (length value)))))))) - -(defun widget-sublist (list start &optional end) - "Return the sublist of LIST from START to END. -If END is omitted, it defaults to the length of LIST." - (if (> start 0) (setq list (nthcdr start list))) - (if end - (if (<= end start) - nil - (setq list (copy-sequence list)) - (setcdr (nthcdr (- end start 1) list) nil) - list) - (copy-sequence list))) - -(defun widget-item-action (widget &optional event) - ;; Just notify itself. - (widget-apply widget :notify widget event)) - -;;; The `push-button' Widget. - -(defcustom widget-push-button-gui widget-glyph-enable - "If non nil, use GUI push buttons when available." - :group 'widgets - :type 'boolean) - -;; Cache already created GUI objects. -(defvar widget-push-button-cache nil) - -(defcustom widget-push-button-prefix "[" - "String used as prefix for buttons." - :type 'string - :group 'widget-button) - -(defcustom widget-push-button-suffix "]" - "String used as suffix for buttons." - :type 'string - :group 'widget-button) - -(define-widget 'push-button 'item - "A pushable button." - :button-prefix "" - :button-suffix "" - :value-create 'widget-push-button-value-create - :format "%[%v%]") - -(defun widget-push-button-value-create (widget) - ;; Insert text representing the `on' and `off' states. - (let* ((tag (or (widget-get widget :tag) - (widget-get widget :value))) - (tag-glyph (widget-get widget :tag-glyph)) - (text (concat widget-push-button-prefix - tag widget-push-button-suffix)) - (gui-glyphs (lax-plist-get widget-push-button-cache tag))) - (cond (tag-glyph - (widget-glyph-insert widget text tag-glyph)) - ;; We must check for console-on-window-system-p here, - ;; because GUI will not work otherwise (it needs RGB - ;; components for colors, and they are not known on TTYs). - ((and widget-push-button-gui - (console-on-window-system-p)) - (unless gui-glyphs - (let* ((gui-button-shadow-thickness 1) - (gui (make-gui-button tag 'widget-gui-action widget))) - (setq - gui-glyphs - (list - (make-glyph `(,(nth 0 (aref gui 1)) [string :data ,text])) - (make-glyph `(,(nth 1 (aref gui 1)) [string :data ,text])) - (make-glyph `(,(nth 2 (aref gui 1)) [string :data ,text])))) - (laxputf widget-push-button-cache tag gui-glyphs))) - (widget-glyph-insert-glyph - widget (nth 0 gui-glyphs) (nth 1 gui-glyphs) (nth 2 gui-glyphs))) - (t - (insert text))))) - -(defun widget-gui-action (widget) - "Apply :action for WIDGET." - (widget-apply-action widget (this-command-keys))) - -;;; The `link' Widget. - -(defcustom widget-link-prefix "[" - "String used as prefix for links." - :type 'string - :group 'widget-button) - -(defcustom widget-link-suffix "]" - "String used as suffix for links." - :type 'string - :group 'widget-button) - -(define-widget 'link 'item - "An embedded link." - :button-prefix 'widget-link-prefix - :button-suffix 'widget-link-suffix - :help-echo "Follow the link" - :format "%[%t%]") - -;;; The `info-link' Widget. - -(define-widget 'info-link 'link - "A link to an info file." - :help-echo 'widget-info-link-help-echo - :action 'widget-info-link-action) - -(defun widget-info-link-help-echo (widget) - (concat "Read the manual entry `" (widget-value widget) "'")) - -(defun widget-info-link-action (widget &optional event) - "Open the info node specified by WIDGET." - (Info-goto-node (widget-value widget))) - -;;; The `url-link' Widget. - -(define-widget 'url-link 'link - "A link to an www page." - :help-echo 'widget-url-link-help-echo - :action 'widget-url-link-action) - -(defun widget-url-link-help-echo (widget) - (concat "Visit ")) - -(defun widget-url-link-action (widget &optional event) - "Open the url specified by WIDGET." - (require 'browse-url) - (funcall browse-url-browser-function (widget-value widget))) - -;;; The `function-link' Widget. - -(define-widget 'function-link 'link - "A link to an Emacs function." - :action 'widget-function-link-action) - -(defun widget-function-link-action (widget &optional event) - "Show the function specified by WIDGET." - (describe-function (widget-value widget))) - -;;; The `variable-link' Widget. - -(define-widget 'variable-link 'link - "A link to an Emacs variable." - :action 'widget-variable-link-action) - -(defun widget-variable-link-action (widget &optional event) - "Show the variable specified by WIDGET." - (describe-variable (widget-value widget))) - -;;; The `file-link' Widget. - -(define-widget 'file-link 'link - "A link to a file." - :action 'widget-file-link-action) - -(defun widget-file-link-action (widget &optional event) - "Find the file specified by WIDGET." - (find-file (widget-value widget))) - -;;; The `emacs-library-link' Widget. - -(define-widget 'emacs-library-link 'link - "A link to an Emacs Lisp library file." - :help-echo 'widget-emacs-library-link-help-echo - :action 'widget-emacs-library-link-action) - -(defun widget-emacs-library-link-help-echo (widget) - (concat "Visit " (widget-value widget))) - -(defun widget-emacs-library-link-action (widget &optional event) - "Find the Emacs Library file specified by WIDGET." - (find-file (locate-library (widget-value widget)))) - -;;; The `emacs-commentary-link' Widget. - -(define-widget 'emacs-commentary-link 'link - "A link to Commentary in an Emacs Lisp library file." - :action 'widget-emacs-commentary-link-action) - -(defun widget-emacs-commentary-link-action (widget &optional event) - "Find the Commentary section of the Emacs file specified by WIDGET." - (finder-commentary (widget-value widget))) - -;;; The `editable-field' Widget. - -(define-widget 'editable-field 'default - "An editable text field." - :convert-widget 'widget-value-convert-widget - :keymap widget-field-keymap - :format "%v" - :value "" - :prompt-internal 'widget-field-prompt-internal - :prompt-history 'widget-field-history - :prompt-value 'widget-field-prompt-value - :action 'widget-field-action - :validate 'widget-field-validate - :valid-regexp "" - :error "No match" - :value-create 'widget-field-value-create - :value-delete 'widget-field-value-delete - :value-get 'widget-field-value-get - :match 'widget-field-match) - -(defvar widget-field-history nil - "History of field minibuffer edits.") - -(defun widget-field-prompt-internal (widget prompt initial history) - ;; Read string for WIDGET prompting with PROMPT. - ;; INITIAL is the initial input and HISTORY is a symbol containing - ;; the earlier input. - (read-string prompt initial history)) - -(defun widget-field-prompt-value (widget prompt value unbound) - ;; Prompt for a string. - (let ((initial (if unbound - nil - (cons (widget-apply widget :value-to-internal - value) 0))) - (history (widget-get widget :prompt-history))) - (let ((answer (widget-apply widget - :prompt-internal prompt initial history))) - (widget-apply widget :value-to-external answer)))) - -(defvar widget-edit-functions nil) - -(defun widget-field-action (widget &optional event) - ;; Edit the value in the minibuffer. - (let* ((invalid (widget-apply widget :validate)) - (prompt (concat (widget-apply widget :menu-tag-get) ": ")) - (value (unless invalid - (widget-value widget))) - (answer (widget-apply widget :prompt-value prompt value invalid))) - (unless (equal value answer) - ;; This is a hack. We can't properly validate the widget - ;; because validation requires the new value to be in the field. - ;; However, widget-field-value-create will not function unless - ;; the new value matches. So, we check whether the thing - ;; matches, and if it does, use either the real or a dummy error - ;; message. - (unless (widget-apply widget :match answer) - (let ((error-message (or (widget-get widget :type-error) - "Invalid field contents"))) - (widget-put widget :error error-message) - (error error-message))) - (widget-value-set widget answer) - (widget-apply widget :notify widget event) - (widget-setup)) - (run-hook-with-args 'widget-edit-functions widget))) - -;(defun widget-field-action (widget &optional event) -; ;; Move to next field. -; (widget-forward 1) -; (run-hook-with-args 'widget-edit-functions widget)) - -(defun widget-field-validate (widget) - ;; Valid if the content matches `:valid-regexp'. - (save-excursion - (let ((value (widget-apply widget :value-get)) - (regexp (widget-get widget :valid-regexp))) - (if (string-match regexp value) - nil - widget)))) - -(defun widget-field-value-create (widget) - ;; Create an editable text field. - (let ((size (widget-get widget :size)) - (value (widget-get widget :value)) - (from (point)) - ;; This is changed to a real extent in `widget-setup'. We - ;; need the end points to behave differently until - ;; `widget-setup' is called. Should probably be replaced with - ;; a genuine extent, but some things break, then. - (extent (cons (make-marker) (make-marker)))) - (widget-put widget :field-extent extent) - (insert value) - (and size - (< (length value) size) - (insert-char ?\ (- size (length value)))) - (unless (memq widget widget-field-list) - (push widget widget-field-new)) - (move-marker (cdr extent) (point)) - (set-marker-insertion-type (cdr extent) nil) - (when (null size) - (insert ?\n)) - (move-marker (car extent) from) - (set-marker-insertion-type (car extent) t))) - -(defun widget-field-value-delete (widget) - ;; Remove the widget from the list of active editing fields. - (setq widget-field-list (delq widget widget-field-list)) - ;; These are nil if the :format string doesn't contain `%v'. - (let ((extent (widget-get widget :field-extent))) - (when extent - (detach-extent extent)))) - -(defun widget-field-value-get (widget) - ;; Return current text in editing field. - (let ((from (widget-field-start widget)) - (to (widget-field-end widget)) - (buffer (widget-field-buffer widget)) - (size (widget-get widget :size)) - (secret (widget-get widget :secret)) - (old (current-buffer))) - (cond - ((and from to) - (set-buffer buffer) - (while (and size - (not (zerop size)) - (> to from) - (eq (char-after (1- to)) ?\ )) - (setq to (1- to))) - (let ((result (buffer-substring-no-properties from to))) - (when secret - (let ((index 0)) - (while (< (+ from index) to) - (aset result index - (get-char-property (+ from index) 'secret)) - (incf index)))) - (set-buffer old) - result)) - (t - (widget-get widget :value))))) - -(defun widget-field-match (widget value) - ;; Match any string. - (stringp value)) - -;;; The `text' Widget. - -(define-widget 'text 'editable-field - :keymap widget-text-keymap - "A multiline text area.") - -;;; The `menu-choice' Widget. - -(define-widget 'menu-choice 'default - "A menu of options." - :convert-widget 'widget-types-convert-widget - :format "%[%t%]: %v" - :case-fold t - :tag "choice" - :void '(item :format "invalid (%t)\n") - :value-create 'widget-choice-value-create - :value-delete 'widget-children-value-delete - :value-get 'widget-choice-value-get - :value-inline 'widget-choice-value-inline - :mouse-down-action 'widget-choice-mouse-down-action - :action 'widget-choice-action - :error "Make a choice" - :validate 'widget-choice-validate - :match 'widget-choice-match - :match-inline 'widget-choice-match-inline) - -(defun widget-choice-value-create (widget) - ;; Insert the first choice that matches the value. - (let ((value (widget-get widget :value)) - (args (widget-get widget :args)) - current) - (while args - (setq current (car args) - args (cdr args)) - (when (widget-apply current :match value) - (widget-put widget :children (list (widget-create-child-value - widget current value))) - (widget-put widget :choice current) - (setq args nil - current nil))) - (when current - (let ((void (widget-get widget :void))) - (widget-put widget :children (list (widget-create-child-and-convert - widget void :value value))) - (widget-put widget :choice void))))) - -(defun widget-choice-value-get (widget) - ;; Get value of the child widget. - (widget-value (car (widget-get widget :children)))) - -(defun widget-choice-value-inline (widget) - ;; Get value of the child widget. - (widget-apply (car (widget-get widget :children)) :value-inline)) - -(defcustom widget-choice-toggle nil - "If non-nil, a binary choice will just toggle between the values. -Otherwise, the user will explicitly have to choose between the values -when he invoked the menu." - :type 'boolean - :group 'widgets) - -(defun widget-choice-mouse-down-action (widget &optional event) - ;; Return non-nil if we need a menu. - (let ((args (widget-get widget :args)) - (old (widget-get widget :choice))) - (cond ((not (console-on-window-system-p)) - ;; No place to pop up a menu. - nil) - ((< (length args) 2) - ;; Empty or singleton list, just return the value. - nil) - ((> (length args) widget-menu-max-size) - ;; Too long, prompt. - nil) - ((> (length args) 2) - ;; Reasonable sized list, use menu. - t) - ((and widget-choice-toggle (memq old args)) - ;; We toggle. - nil) - (t - ;; Ask which of the two. - t)))) - -(defun widget-choice-action (widget &optional event) - ;; Make a choice. - (let ((args (widget-get widget :args)) - (old (widget-get widget :choice)) - (tag (widget-apply widget :menu-tag-get)) - (completion-ignore-case (widget-get widget :case-fold)) - current choices) - ;; Remember old value. - (if (and old (not (widget-apply widget :validate))) - (let* ((external (widget-value widget)) - (internal (widget-apply old :value-to-internal external))) - (widget-put old :value internal))) - ;; Find new choice. - (setq current - (cond ((= (length args) 0) - nil) - ((= (length args) 1) - (nth 0 args)) - ((and widget-choice-toggle - (= (length args) 2) - (memq old args)) - (if (eq old (nth 0 args)) - (nth 1 args) - (nth 0 args))) - (t - (while args - (setq current (car args) - args (cdr args)) - (setq choices - (cons (cons (widget-apply current :menu-tag-get) - current) - choices))) - (widget-choose tag (reverse choices) event)))) - (when current - (widget-value-set widget - (widget-apply current :value-to-external - (widget-get current :value))) - (widget-setup) - (widget-apply widget :notify widget event))) - (run-hook-with-args 'widget-edit-functions widget)) - -(defun widget-choice-validate (widget) - ;; Valid if we have made a valid choice. - (let ((void (widget-get widget :void)) - (choice (widget-get widget :choice)) - (child (car (widget-get widget :children)))) - (if (eq void choice) - widget - (widget-apply child :validate)))) - -(defun widget-choice-match (widget value) - ;; Matches if one of the choices matches. - (let ((args (widget-get widget :args)) - current found) - (while (and args (not found)) - (setq current (car args) - args (cdr args) - found (widget-apply current :match value))) - found)) - -(defun widget-choice-match-inline (widget values) - ;; Matches if one of the choices matches. - (let ((args (widget-get widget :args)) - current found) - (while (and args (null found)) - (setq current (car args) - args (cdr args) - found (widget-match-inline current values))) - found)) - -;;; The `toggle' Widget. - -(define-widget 'toggle 'item - "Toggle between two states." - :format "%[%v%]\n" - :value-create 'widget-toggle-value-create - :action 'widget-toggle-action - :match (lambda (widget value) t) - :on "on" - :off "off") - -(defun widget-toggle-value-create (widget) - ;; Insert text representing the `on' and `off' states. - (if (widget-value widget) - (widget-glyph-insert widget - (widget-get widget :on) - (widget-get widget :on-glyph)) - (widget-glyph-insert widget - (widget-get widget :off) - (widget-get widget :off-glyph)))) - -(defun widget-toggle-action (widget &optional event) - ;; Toggle value. - (widget-value-set widget (not (widget-value widget))) - (widget-apply widget :notify widget event) - (run-hook-with-args 'widget-edit-functions widget)) - -;;; The `checkbox' Widget. - -(define-widget 'checkbox 'toggle - "A checkbox toggle." - :button-suffix "" - :button-prefix "" - :format "%[%v%]" - :on "[X]" - :on-glyph "check1" - :off "[ ]" - :off-glyph "check0" - :action 'widget-checkbox-action) - -(defun widget-checkbox-action (widget &optional event) - "Toggle checkbox, notify parent, and set active state of sibling." - (widget-toggle-action widget event) - (let ((sibling (widget-get-sibling widget))) - (when sibling - (if (widget-value widget) - (widget-apply sibling :activate) - (widget-apply sibling :deactivate))))) - -;;; The `checklist' Widget. - -(define-widget 'checklist 'default - "A multiple choice widget." - :convert-widget 'widget-types-convert-widget - :format "%v" - :offset 4 - :entry-format "%b %v" - :menu-tag "checklist" - :greedy nil - :value-create 'widget-checklist-value-create - :value-delete 'widget-children-value-delete - :value-get 'widget-checklist-value-get - :validate 'widget-checklist-validate - :match 'widget-checklist-match - :match-inline 'widget-checklist-match-inline) - -(defun widget-checklist-value-create (widget) - ;; Insert all values - (let ((alist (widget-checklist-match-find widget (widget-get widget :value))) - (args (widget-get widget :args))) - (while args - (widget-checklist-add-item widget (car args) (assq (car args) alist)) - (setq args (cdr args))) - (widget-put widget :children (nreverse (widget-get widget :children))))) - -(defun widget-checklist-add-item (widget type chosen) - ;; Create checklist item in WIDGET of type TYPE. - ;; If the item is checked, CHOSEN is a cons whose cdr is the value. - (and (eq (preceding-char) ?\n) - (widget-get widget :indent) - (insert-char ?\ (widget-get widget :indent))) - (widget-specify-insert - (let* ((children (widget-get widget :children)) - (buttons (widget-get widget :buttons)) - (button-args (or (widget-get type :sibling-args) - (widget-get widget :button-args))) - (from (point)) - child button) - (insert (widget-get widget :entry-format)) - (goto-char from) - ;; Parse % escapes in format. - (while (re-search-forward "%\\([bv%]\\)" nil t) - (let ((escape (aref (match-string 1) 0))) - (replace-match "" t t) - (cond ((eq escape ?%) - (insert "%")) - ((eq escape ?b) - (setq button (apply 'widget-create-child-and-convert - widget 'checkbox - :value (not (null chosen)) - button-args))) - ((eq escape ?v) - (setq child - (cond ((not chosen) - (let ((child (widget-create-child widget type))) - (widget-apply child :deactivate) - child)) - ((widget-get type :inline) - (widget-create-child-value - widget type (cdr chosen))) - (t - (widget-create-child-value - widget type (car (cdr chosen))))))) - (t - (error "Unknown escape `%c'" escape))))) - ;; Update properties. - (and button child (widget-put child :button button)) - (and button (widget-put widget :buttons (cons button buttons))) - (and child (widget-put widget :children (cons child children)))))) - -(defun widget-checklist-match (widget values) - ;; All values must match a type in the checklist. - (and (listp values) - (null (cdr (widget-checklist-match-inline widget values))))) - -(defun widget-checklist-match-inline (widget values) - ;; Find the values which match a type in the checklist. - (let ((greedy (widget-get widget :greedy)) - (args (copy-sequence (widget-get widget :args))) - found rest) - (while values - (let ((answer (widget-checklist-match-up args values))) - (cond (answer - (let ((vals (widget-match-inline answer values))) - (setq found (append found (car vals)) - values (cdr vals) - args (delq answer args)))) - (greedy - (setq rest (append rest (list (car values))) - values (cdr values))) - (t - (setq rest (append rest values) - values nil))))) - (cons found rest))) - -(defun widget-checklist-match-find (widget vals) - ;; Find the vals which match a type in the checklist. - ;; Return an alist of (TYPE MATCH). - (let ((greedy (widget-get widget :greedy)) - (args (copy-sequence (widget-get widget :args))) - found) - (while vals - (let ((answer (widget-checklist-match-up args vals))) - (cond (answer - (let ((match (widget-match-inline answer vals))) - (setq found (cons (cons answer (car match)) found) - vals (cdr match) - args (delq answer args)))) - (greedy - (setq vals (cdr vals))) - (t - (setq vals nil))))) - found)) - -(defun widget-checklist-match-up (args vals) - ;; Rerturn the first type from ARGS that matches VALS. - (let (current found) - (while (and args (null found)) - (setq current (car args) - args (cdr args) - found (widget-match-inline current vals))) - (if found - current - nil))) - -(defun widget-checklist-value-get (widget) - ;; The values of all selected items. - (let ((children (widget-get widget :children)) - child result) - (while children - (setq child (car children) - children (cdr children)) - (if (widget-value (widget-get child :button)) - (setq result (append result (widget-apply child :value-inline))))) - result)) - -(defun widget-checklist-validate (widget) - ;; Ticked chilren must be valid. - (let ((children (widget-get widget :children)) - child button found) - (while (and children (not found)) - (setq child (car children) - children (cdr children) - button (widget-get child :button) - found (and (widget-value button) - (widget-apply child :validate)))) - found)) - -;;; The `option' Widget - -(define-widget 'option 'checklist - "An widget with an optional item." - :inline t) - -;;; The `choice-item' Widget. - -(define-widget 'choice-item 'item - "Button items that delegate action events to their parents." - :action 'widget-parent-action - :format "%[%t%] \n") - -;;; The `radio-button' Widget. - -(define-widget 'radio-button 'toggle - "A radio button for use in the `radio' widget." - :notify 'widget-radio-button-notify - :format "%[%v%]" - :button-suffix "" - :button-prefix "" - :on "(*)" - :on-glyph '("radio1" nil "radio0") - :off "( )" - :off-glyph "radio0") - -(defun widget-radio-button-notify (widget child &optional event) - ;; Tell daddy. - (widget-apply (widget-get widget :parent) :action widget event)) - -;;; The `radio-button-choice' Widget. - -(define-widget 'radio-button-choice 'default - "Select one of multiple options." - :convert-widget 'widget-types-convert-widget - :offset 4 - :format "%v" - :entry-format "%b %v" - :menu-tag "radio" - :value-create 'widget-radio-value-create - :value-delete 'widget-children-value-delete - :value-get 'widget-radio-value-get - :value-inline 'widget-radio-value-inline - :value-set 'widget-radio-value-set - :error "You must push one of the buttons" - :validate 'widget-radio-validate - :match 'widget-choice-match - :match-inline 'widget-choice-match-inline - :action 'widget-radio-action) - -(defun widget-radio-value-create (widget) - ;; Insert all values - (let ((args (widget-get widget :args)) - arg) - (while args - (setq arg (car args) - args (cdr args)) - (widget-radio-add-item widget arg)))) - -(defun widget-radio-add-item (widget type) - "Add to radio widget WIDGET a new radio button item of type TYPE." - ;; (setq type (widget-convert type)) - (and (eq (preceding-char) ?\n) - (widget-get widget :indent) - (insert-char ?\ (widget-get widget :indent))) - (widget-specify-insert - (let* ((value (widget-get widget :value)) - (children (widget-get widget :children)) - (buttons (widget-get widget :buttons)) - (button-args (or (widget-get type :sibling-args) - (widget-get widget :button-args))) - (from (point)) - (chosen (and (null (widget-get widget :choice)) - (widget-apply type :match value))) - child button) - (insert (widget-get widget :entry-format)) - (goto-char from) - ;; Parse % escapes in format. - (while (re-search-forward "%\\([bv%]\\)" nil t) - (let ((escape (aref (match-string 1) 0))) - (replace-match "" t t) - (cond ((eq escape ?%) - (insert "%")) - ((eq escape ?b) - (setq button (apply 'widget-create-child-and-convert - widget 'radio-button - :value (not (null chosen)) - button-args))) - ((eq escape ?v) - (setq child (if chosen - (widget-create-child-value - widget type value) - (widget-create-child widget type))) - (unless chosen - (widget-apply child :deactivate))) - (t - (error "Unknown escape `%c'" escape))))) - ;; Update properties. - (when chosen - (widget-put widget :choice type)) - (when button - (widget-put child :button button) - (widget-put widget :buttons (nconc buttons (list button)))) - (when child - (widget-put widget :children (nconc children (list child)))) - child))) - -(defun widget-radio-value-get (widget) - ;; Get value of the child widget. - (let ((chosen (widget-radio-chosen widget))) - (and chosen (widget-value chosen)))) - -(defun widget-radio-chosen (widget) - "Return the widget representing the chosen radio button." - (let ((children (widget-get widget :children)) - current found) - (while children - (setq current (car children) - children (cdr children)) - (let* ((button (widget-get current :button)) - (value (widget-apply button :value-get))) - (when value - (setq found current - children nil)))) - found)) - -(defun widget-radio-value-inline (widget) - ;; Get value of the child widget. - (let ((children (widget-get widget :children)) - current found) - (while children - (setq current (car children) - children (cdr children)) - (let* ((button (widget-get current :button)) - (value (widget-apply button :value-get))) - (when value - (setq found (widget-apply current :value-inline) - children nil)))) - found)) - -(defun widget-radio-value-set (widget value) - ;; We can't just delete and recreate a radio widget, since children - ;; can be added after the original creation and won't be recreated - ;; by `:create'. - (let ((children (widget-get widget :children)) - current found) - (while children - (setq current (car children) - children (cdr children)) - (let* ((button (widget-get current :button)) - (match (and (not found) - (widget-apply current :match value)))) - (widget-value-set button match) - (if match - (progn - (widget-value-set current value) - (widget-apply current :activate)) - (widget-apply current :deactivate)) - (setq found (or found match)))))) - -(defun widget-radio-validate (widget) - ;; Valid if we have made a valid choice. - (let ((children (widget-get widget :children)) - current found button) - (while (and children (not found)) - (setq current (car children) - children (cdr children) - button (widget-get current :button) - found (widget-apply button :value-get))) - (if found - (widget-apply current :validate) - widget))) - -(defun widget-radio-action (widget child event) - ;; Check if a radio button was pressed. - (let ((children (widget-get widget :children)) - (buttons (widget-get widget :buttons)) - current) - (when (memq child buttons) - (while children - (setq current (car children) - children (cdr children)) - (let* ((button (widget-get current :button))) - (cond ((eq child button) - (widget-value-set button t) - (widget-apply current :activate)) - ((widget-value button) - (widget-value-set button nil) - (widget-apply current :deactivate))))))) - ;; Pass notification to parent. - (widget-apply widget :notify child event)) - -;;; The `insert-button' Widget. - -(define-widget 'insert-button 'push-button - "An insert button for the `editable-list' widget." - :tag "INS" - :help-echo "Insert a new item into the list at this position" - :action 'widget-insert-button-action) - -(defun widget-insert-button-action (widget &optional event) - ;; Ask the parent to insert a new item. - (widget-apply (widget-get widget :parent) - :insert-before (widget-get widget :widget))) - -;;; The `delete-button' Widget. - -(define-widget 'delete-button 'push-button - "A delete button for the `editable-list' widget." - :tag "DEL" - :help-echo "Delete this item from the list" - :action 'widget-delete-button-action) - -(defun widget-delete-button-action (widget &optional event) - ;; Ask the parent to insert a new item. - (widget-apply (widget-get widget :parent) - :delete-at (widget-get widget :widget))) - -;;; The `editable-list' Widget. - -(defcustom widget-editable-list-gui nil - "If non nil, use GUI push-buttons in editable list when available." - :type 'boolean - :group 'widgets) - -(define-widget 'editable-list 'default - "A variable list of widgets of the same type." - :convert-widget 'widget-types-convert-widget - :offset 12 - :format "%v%i\n" - :format-handler 'widget-editable-list-format-handler - :entry-format "%i %d %v" - :menu-tag "editable-list" - :value-create 'widget-editable-list-value-create - :value-delete 'widget-children-value-delete - :value-get 'widget-editable-list-value-get - :validate 'widget-children-validate - :match 'widget-editable-list-match - :match-inline 'widget-editable-list-match-inline - :insert-before 'widget-editable-list-insert-before - :delete-at 'widget-editable-list-delete-at) - -(defun widget-editable-list-format-handler (widget escape) - ;; We recognize the insert button. - (let ((widget-push-button-gui widget-editable-list-gui)) - (cond ((eq escape ?i) - (and (widget-get widget :indent) - (insert-char ?\ (widget-get widget :indent))) - (apply 'widget-create-child-and-convert - widget 'insert-button - (widget-get widget :append-button-args))) - (t - (widget-default-format-handler widget escape))))) - -(defun widget-editable-list-value-create (widget) - ;; Insert all values - (let* ((value (widget-get widget :value)) - (type (nth 0 (widget-get widget :args))) - (inlinep (widget-get type :inline)) - children) - (widget-put widget :value-pos (copy-marker (point))) - (set-marker-insertion-type (widget-get widget :value-pos) t) - (while value - (let ((answer (widget-match-inline type value))) - (if answer - (setq children (cons (widget-editable-list-entry-create - widget - (if inlinep - (car answer) - (car (car answer))) - t) - children) - value (cdr answer)) - (setq value nil)))) - (widget-put widget :children (nreverse children)))) - -(defun widget-editable-list-value-get (widget) - ;; Get value of the child widget. - (apply 'append (mapcar (lambda (child) (widget-apply child :value-inline)) - (widget-get widget :children)))) - -(defun widget-editable-list-match (widget value) - ;; Value must be a list and all the members must match the type. - (and (listp value) - (null (cdr (widget-editable-list-match-inline widget value))))) - -(defun widget-editable-list-match-inline (widget value) - (let ((type (nth 0 (widget-get widget :args))) - (ok t) - found) - (while (and value ok) - (let ((answer (widget-match-inline type value))) - (if answer - (setq found (append found (car answer)) - value (cdr answer)) - (setq ok nil)))) - (cons found value))) - -(defun widget-editable-list-insert-before (widget before) - ;; Insert a new child in the list of children. - (save-excursion - (let ((children (widget-get widget :children)) - (inhibit-read-only t) - before-change-functions - after-change-functions) - (cond (before - (goto-char (widget-get before :entry-from))) - (t - (goto-char (widget-get widget :value-pos)))) - (let ((child (widget-editable-list-entry-create - widget nil nil))) - (when (< (widget-get child :entry-from) (widget-get widget :from)) - (set-marker (widget-get widget :from) - (widget-get child :entry-from))) - (if (eq (car children) before) - (widget-put widget :children (cons child children)) - (while (not (eq (car (cdr children)) before)) - (setq children (cdr children))) - (setcdr children (cons child (cdr children))))))) - (widget-setup) - (widget-apply widget :notify widget)) - -(defun widget-editable-list-delete-at (widget child) - ;; Delete child from list of children. - (save-excursion - (let ((buttons (copy-sequence (widget-get widget :buttons))) - button - (inhibit-read-only t) - before-change-functions - after-change-functions) - (while buttons - (setq button (car buttons) - buttons (cdr buttons)) - (when (eq (widget-get button :widget) child) - (widget-put widget - :buttons (delq button (widget-get widget :buttons))) - (widget-delete button)))) - (let ((entry-from (widget-get child :entry-from)) - (entry-to (widget-get child :entry-to)) - (inhibit-read-only t) - before-change-functions - after-change-functions) - (widget-delete child) - (delete-region entry-from entry-to) - (set-marker entry-from nil) - (set-marker entry-to nil)) - (widget-put widget :children (delq child (widget-get widget :children)))) - (widget-setup) - (widget-apply widget :notify widget)) - -(defun widget-editable-list-entry-create (widget value conv) - ;; Create a new entry to the list. - (let ((type (nth 0 (widget-get widget :args))) - (widget-push-button-gui widget-editable-list-gui) - child delete insert) - (widget-specify-insert - (save-excursion - (and (widget-get widget :indent) - (insert-char ?\ (widget-get widget :indent))) - (insert (widget-get widget :entry-format))) - ;; Parse % escapes in format. - (while (re-search-forward "%\\(.\\)" nil t) - (let ((escape (aref (match-string 1) 0))) - (replace-match "" t t) - (cond ((eq escape ?%) - (insert "%")) - ((eq escape ?i) - (setq insert (apply 'widget-create-child-and-convert - widget 'insert-button - (widget-get widget :insert-button-args)))) - ((eq escape ?d) - (setq delete (apply 'widget-create-child-and-convert - widget 'delete-button - (widget-get widget :delete-button-args)))) - ((eq escape ?v) - (if conv - (setq child (widget-create-child-value - widget type value)) - (setq child (widget-create-child widget type)))) - (t - (error "Unknown escape `%c'" escape))))) - (widget-put widget - :buttons (cons delete - (cons insert - (widget-get widget :buttons)))) - (let ((entry-from (copy-marker (point-min))) - (entry-to (copy-marker (point-max)))) - (set-marker-insertion-type entry-from t) - (set-marker-insertion-type entry-to nil) - (widget-put child :entry-from entry-from) - (widget-put child :entry-to entry-to))) - (widget-put insert :widget child) - (widget-put delete :widget child) - child)) - -;;; The `group' Widget. - -(define-widget 'group 'default - "A widget which group other widgets inside." - :convert-widget 'widget-types-convert-widget - :format "%v" - :value-create 'widget-group-value-create - :value-delete 'widget-children-value-delete - :value-get 'widget-editable-list-value-get - :validate 'widget-children-validate - :match 'widget-group-match - :match-inline 'widget-group-match-inline) - -(defun widget-group-value-create (widget) - ;; Create each component. - (let ((args (widget-get widget :args)) - (value (widget-get widget :value)) - arg answer children) - (while args - (setq arg (car args) - args (cdr args) - answer (widget-match-inline arg value) - value (cdr answer)) - (and (eq (preceding-char) ?\n) - (widget-get widget :indent) - (insert-char ?\ (widget-get widget :indent))) - (push (cond ((null answer) - (widget-create-child widget arg)) - ((widget-get arg :inline) - (widget-create-child-value widget arg (car answer))) - (t - (widget-create-child-value widget arg (car (car answer))))) - children)) - (widget-put widget :children (nreverse children)))) - -(defun widget-group-match (widget values) - ;; Match if the components match. - (and (listp values) - (let ((match (widget-group-match-inline widget values))) - (and match (null (cdr match)))))) - -(defun widget-group-match-inline (widget vals) - ;; Match if the components match. - (let ((args (widget-get widget :args)) - argument answer found) - (while args - (setq argument (car args) - args (cdr args) - answer (widget-match-inline argument vals)) - (if answer - (setq vals (cdr answer) - found (append found (car answer))) - (setq vals nil - args nil))) - (if answer - (cons found vals) - nil))) - -;;; The `visibility' Widget. - -(define-widget 'visibility 'item - "An indicator and manipulator for hidden items." - :format "%[%v%]" - :button-prefix "" - :button-suffix "" - :on "Hide" - :off "Show" - :value-create 'widget-visibility-value-create - :action 'widget-toggle-action - :match (lambda (widget value) t)) - -(defun widget-visibility-value-create (widget) - ;; Insert text representing the `on' and `off' states. - (let ((on (widget-get widget :on)) - (off (widget-get widget :off))) - (if on - (setq on (concat widget-push-button-prefix - on - widget-push-button-suffix)) - (setq on "")) - (if off - (setq off (concat widget-push-button-prefix - off - widget-push-button-suffix)) - (setq off "")) - (if (widget-value widget) - (widget-glyph-insert widget on '("down" "down-pushed")) - (widget-glyph-insert widget off '("right" "right-pushed"))))) - -;;; The `documentation-link' Widget. -;; -;; This is a helper widget for `documentation-string'. - -(define-widget 'documentation-link 'link - "Link type used in documentation strings." - :tab-order -1 - :help-echo 'widget-documentation-link-echo-help - :action 'widget-documentation-link-action) - -(defun widget-documentation-link-echo-help (widget) - "Tell what this link will describe." - (concat "Describe the `" (widget-get widget :value) "' symbol.")) - -(defun widget-documentation-link-action (widget &optional event) - "Display documentation for WIDGET's value. Ignore optional argument EVENT." - (let* ((string (widget-get widget :value)) - (symbol (intern string))) - (if (and (fboundp symbol) (boundp symbol)) - ;; If there are two doc strings, give the user a way to pick one. - (apropos (concat "\\`" (regexp-quote string) "\\'")) - (if (fboundp symbol) - (describe-function symbol) - (describe-variable symbol))))) - -(defcustom widget-documentation-links t - "Add hyperlinks to documentation strings when non-nil." - :type 'boolean - :group 'widget-documentation) - -(defcustom widget-documentation-link-regexp "`\\([^\n`' ]+\\)'" - "Regexp for matching potential links in documentation strings. -The first group should be the link itself." - :type 'regexp - :group 'widget-documentation) - -(defcustom widget-documentation-link-p 'intern-soft - "Predicate used to test if a string is useful as a link. -The value should be a function. The function will be called one -argument, a string, and should return non-nil if there should be a -link for that string." - :type 'function - :options '(widget-documentation-link-p) - :group 'widget-documentation) - -(defcustom widget-documentation-link-type 'documentation-link - "Widget type used for links in documentation strings." - :type 'symbol - :group 'widget-documentation) - -(defun widget-documentation-link-add (widget from to) - (widget-specify-doc widget from to) - (when widget-documentation-links - (let ((regexp widget-documentation-link-regexp) - (predicate widget-documentation-link-p) - (type widget-documentation-link-type) - (buttons (widget-get widget :buttons))) - (save-excursion - (goto-char from) - (while (re-search-forward regexp to t) - (let ((name (match-string 1)) - (begin (match-beginning 1)) - (end (match-end 1))) - (when (funcall predicate name) - (push (widget-convert-button type begin end :value name) - buttons))))) - (widget-put widget :buttons buttons))) - (let ((indent (widget-get widget :indent))) - (when (and indent (not (zerop indent))) - (save-excursion - (save-restriction - (narrow-to-region from to) - (goto-char (point-min)) - (while (search-forward "\n" nil t) - (insert-char ?\ indent))))))) - -;;; The `documentation-string' Widget. - -(define-widget 'documentation-string 'item - "A documentation string." - :format "%v" - :action 'widget-documentation-string-action - :value-delete 'widget-children-value-delete - :value-create 'widget-documentation-string-value-create) - -(defun widget-documentation-string-value-create (widget) - ;; Insert documentation string. - (let ((doc (widget-value widget)) - (indent (widget-get widget :indent)) - (shown (widget-get (widget-get widget :parent) :documentation-shown)) - (start (point))) - (if (string-match "\n" doc) - (let ((before (substring doc 0 (match-beginning 0))) - (after (substring doc (match-beginning 0))) - buttons) - (insert before " ") - (widget-documentation-link-add widget start (point)) - (push (widget-create-child-and-convert - widget 'visibility - :help-echo (lambda (widget) - (concat - (if (widget-value widget) - "Hide" "Show") - " the rest of the documentation")) - :off "More" - :action 'widget-parent-action - shown) - buttons) - (when shown - (setq start (point)) - (when indent - (insert-char ?\ indent)) - (insert after) - (widget-documentation-link-add widget start (point))) - (widget-put widget :buttons buttons)) - (insert doc) - (widget-documentation-link-add widget start (point)))) - (insert "\n")) - -(defun widget-documentation-string-action (widget &rest ignore) - ;; Toggle documentation. - (let ((parent (widget-get widget :parent))) - (widget-put parent :documentation-shown - (not (widget-get parent :documentation-shown)))) - ;; Redraw. - (widget-value-set widget (widget-value widget))) - -;;; The Sexp Widgets. - -(define-widget 'const 'item - "An immutable sexp." - :prompt-value 'widget-const-prompt-value - :format "%t\n%d") - -(defun widget-const-prompt-value (widget prompt value unbound) - ;; Return the value of the const. - (widget-value widget)) - -(define-widget 'function-item 'const - "An immutable function name." - :format "%v\n%h" - :documentation-property (lambda (symbol) - (condition-case nil - (documentation symbol t) - (error nil)))) - -(define-widget 'variable-item 'const - "An immutable variable name." - :format "%v\n%h" - :documentation-property 'variable-documentation) - -(defvar widget-string-prompt-value-history nil - "History of input to `widget-string-prompt-value'.") - -(define-widget 'string 'editable-field - "A string" - :tag "String" - :format "%{%t%}: %v" - :complete-function 'ispell-complete-word - :prompt-history 'widget-string-prompt-value-history) - -(define-widget 'regexp 'string - "A regular expression." - :match 'widget-regexp-match - :validate 'widget-regexp-validate - ;; Doesn't work well with terminating newline. - ;; :value-face 'widget-single-line-field-face - :tag "Regexp") - -(defun widget-regexp-match (widget value) - ;; Match valid regexps. - (and (stringp value) - (condition-case nil - (prog1 t - (string-match value "")) - (error nil)))) - -(defun widget-regexp-validate (widget) - "Check that the value of WIDGET is a valid regexp." - (let ((value (widget-value widget))) - (condition-case data - (prog1 nil - (string-match value "")) - (error (widget-put widget :error (error-message-string data)) - widget)))) - -(define-widget 'file 'string - "A file widget. -It will read a file name from the minibuffer when invoked." - :complete-function 'widget-file-complete - :prompt-value 'widget-file-prompt-value - :format "%{%t%}: %v" - ;; Doesn't work well with terminating newline. - ;; :value-face 'widget-single-line-field-face - :tag "File") - -(defun widget-file-complete () - "Perform completion on file name preceding point." - (interactive) - (let* ((end (point)) - (beg (save-excursion - (skip-chars-backward "^ ") - (point))) - (pattern (buffer-substring beg end)) - (name-part (file-name-nondirectory pattern)) - (directory (file-name-directory pattern)) - (completion (file-name-completion name-part directory))) - (cond ((eq completion t)) - ((null completion) - (message "Can't find completion for \"%s\"" pattern) - (ding)) - ((not (string= name-part completion)) - (delete-region beg end) - (insert (expand-file-name completion directory))) - (t - (message "Making completion list...") - (let ((list (file-name-all-completions name-part directory))) - (setq list (sort list 'string<)) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list list))) - (message "Making completion list...%s" "done"))))) - -(defun widget-file-prompt-value (widget prompt value unbound) - ;; Read file from minibuffer. - (abbreviate-file-name - (if unbound - (read-file-name prompt) - (let ((prompt2 (format "%s (default %s) " prompt value)) - (dir (file-name-directory value)) - (file (file-name-nondirectory value)) - (must-match (widget-get widget :must-match))) - (read-file-name prompt2 dir nil must-match file))))) - -;;;(defun widget-file-action (widget &optional event) -;;; ;; Read a file name from the minibuffer. -;;; (let* ((value (widget-value widget)) -;;; (dir (file-name-directory value)) -;;; (file (file-name-nondirectory value)) -;;; (menu-tag (widget-apply widget :menu-tag-get)) -;;; (must-match (widget-get widget :must-match)) -;;; (answer (read-file-name (concat menu-tag ": (default `" value "') ") -;;; dir nil must-match file))) -;;; (widget-value-set widget (abbreviate-file-name answer)) -;;; (widget-setup) -;;; (widget-apply widget :notify widget event))) - -(define-widget 'directory 'file - "A directory widget. -It will read a directory name from the minibuffer when invoked." - :tag "Directory") - -(defvar widget-symbol-prompt-value-history nil - "History of input to `widget-symbol-prompt-value'.") - -(define-widget 'symbol 'editable-field - "A lisp symbol." - :value nil - :tag "Symbol" - :format "%{%t%}: %v" - :match (lambda (widget value) (symbolp value)) - :complete-function 'lisp-complete-symbol - :prompt-internal 'widget-symbol-prompt-internal - :prompt-match 'symbolp - :prompt-history 'widget-symbol-prompt-value-history - :value-to-internal (lambda (widget value) - (if (symbolp value) - (symbol-name value) - value)) - :value-to-external (lambda (widget value) - (if (stringp value) - (intern value) - value))) - -(defun widget-symbol-prompt-internal (widget prompt initial history) - ;; Read file from minibuffer. - (let ((answer (completing-read prompt obarray - (widget-get widget :prompt-match) - nil initial history))) - (if (and (stringp answer) - (not (zerop (length answer)))) - answer - (error "No value")))) - -(defvar widget-function-prompt-value-history nil - "History of input to `widget-function-prompt-value'.") - -(define-widget 'function 'sexp - "A lisp function." - :complete-function 'lisp-complete-symbol - :prompt-value 'widget-field-prompt-value - :prompt-internal 'widget-symbol-prompt-internal - :prompt-match 'fboundp - :prompt-history 'widget-function-prompt-value-history - :action 'widget-field-action - :tag "Function") - -(defvar widget-variable-prompt-value-history nil - "History of input to `widget-variable-prompt-value'.") - -(define-widget 'variable 'symbol - ;; Should complete on variables. - "A lisp variable." - :prompt-match 'boundp - :prompt-history 'widget-variable-prompt-value-history - :tag "Variable") - -;; This part issues a warning when compiling without Mule. Is there a -;; way of shutting it up? -;; -;; OK, I'll simply comment the whole thing out, until someone decides -;; to do something with it. -;(defvar widget-coding-system-prompt-value-history nil -; "History of input to `widget-coding-system-prompt-value'.") - -;(define-widget 'coding-system 'symbol -; "A MULE coding-system." -; :format "%{%t%}: %v" -; :tag "Coding system" -; :prompt-history 'widget-coding-system-prompt-value-history -; :prompt-value 'widget-coding-system-prompt-value -; :action 'widget-coding-system-action) - -;(defun widget-coding-system-prompt-value (widget prompt value unbound) -; ;; Read coding-system from minibuffer. -; (intern -; (completing-read (format "%s (default %s) " prompt value) -; (mapcar (lambda (sym) -; (list (symbol-name sym))) -; (coding-system-list))))) - -;(defun widget-coding-system-action (widget &optional event) -; ;; Read a file name from the minibuffer. -; (let ((answer -; (widget-coding-system-prompt-value -; widget -; (widget-apply widget :menu-tag-get) -; (widget-value widget) -; t))) -; (widget-value-set widget answer) -; (widget-apply widget :notify widget event) -; (widget-setup))) - -(define-widget 'sexp 'editable-field - "An arbitrary lisp expression." - :tag "Lisp expression" - :format "%{%t%}: %v" - :value nil - :validate 'widget-sexp-validate - :match (lambda (widget value) t) - :value-to-internal 'widget-sexp-value-to-internal - :value-to-external (lambda (widget value) (read value)) - :prompt-history 'widget-sexp-prompt-value-history - :prompt-value 'widget-sexp-prompt-value) - -(defun widget-sexp-value-to-internal (widget value) - ;; Use pp for printer representation. - (let ((pp (if (symbolp value) - (prin1-to-string value) - (pp-to-string value)))) - (while (string-match "\n\\'" pp) - (setq pp (substring pp 0 -1))) - (if (or (string-match "\n\\'" pp) - (> (length pp) 40)) - (concat "\n" pp) - pp))) - -(defun widget-sexp-validate (widget) - ;; Valid if we can read the string and there is no junk left after it. - (save-excursion - (let ((buffer (set-buffer (get-buffer-create " *Widget Scratch*")))) - (erase-buffer) - (insert (widget-apply widget :value-get)) - (goto-char (point-min)) - (condition-case data - (let ((value (read buffer))) - (if (eobp) - (if (widget-apply widget :match value) - nil - (widget-put widget :error (widget-get widget :type-error)) - widget) - (widget-put widget - :error (format "Junk at end of expression: %s" - (buffer-substring (point) - (point-max)))) - widget)) - (error (widget-put widget :error (error-message-string data)) - widget))))) - -(defvar widget-sexp-prompt-value-history nil - "History of input to `widget-sexp-prompt-value'.") - -(defun widget-sexp-prompt-value (widget prompt value unbound) - ;; Read an arbitrary sexp. - (let ((found (read-string prompt - (if unbound nil (cons (prin1-to-string value) 0)) - (widget-get widget :prompt-history)))) - (save-excursion - (let ((buffer (set-buffer (get-buffer-create " *Widget Scratch*")))) - (erase-buffer) - (insert found) - (goto-char (point-min)) - (let ((answer (read buffer))) - (unless (eobp) - (error "Junk at end of expression: %s" - (buffer-substring (point) (point-max)))) - answer))))) - -(define-widget 'restricted-sexp 'sexp - "A Lisp expression restricted to values that match. -To use this type, you must define :match or :match-alternatives." - :type-error "The specified value is not valid" - :match 'widget-restricted-sexp-match - :value-to-internal (lambda (widget value) - (if (widget-apply widget :match value) - (prin1-to-string value) - value))) - -(defun widget-restricted-sexp-match (widget value) - (let ((alternatives (widget-get widget :match-alternatives)) - matched) - (while (and alternatives (not matched)) - (if (cond ((functionp (car alternatives)) - (funcall (car alternatives) value)) - ((and (consp (car alternatives)) - (eq (car (car alternatives)) 'quote)) - (eq value (nth 1 (car alternatives))))) - (setq matched t)) - (setq alternatives (cdr alternatives))) - matched)) - -(define-widget 'integer 'restricted-sexp - "An integer." - :tag "Integer" - :value 0 - :type-error "This field should contain an integer" - :match-alternatives '(integerp)) - -(define-widget 'number 'restricted-sexp - "A floating point number." - :tag "Number" - :value 0.0 - :type-error "This field should contain a number" - :match-alternatives '(numberp)) - -(define-widget 'character 'editable-field - "A character." - :tag "Character" - :value 0 - :size 1 - :format "%{%t%}: %v\n" - :valid-regexp "\\`[\0-\377]\\'" - :error "This field should contain a single character" - :value-to-internal (lambda (widget value) - (if (stringp value) - value - (char-to-string value))) - :value-to-external (lambda (widget value) - (if (stringp value) - (aref value 0) - value)) - :match (lambda (widget value) - (characterp value))) - -(define-widget 'list 'group - "A lisp list." - :tag "List" - :format "%{%t%}:\n%v") - -(define-widget 'vector 'group - "A lisp vector." - :tag "Vector" - :format "%{%t%}:\n%v" - :match 'widget-vector-match - :value-to-internal (lambda (widget value) (append value nil)) - :value-to-external (lambda (widget value) (vconcat value))) - -(defun widget-vector-match (widget value) - (and (vectorp value) - (widget-group-match widget - (widget-apply widget :value-to-internal value)))) - -(define-widget 'cons 'group - "A cons-cell." - :tag "Cons-cell" - :format "%{%t%}:\n%v" - :match 'widget-cons-match - :value-to-internal (lambda (widget value) - (list (car value) (cdr value))) - :value-to-external (lambda (widget value) - (cons (car value) (cadr value)))) - -(defun widget-cons-match (widget value) - (and (consp value) - (widget-group-match widget - (widget-apply widget :value-to-internal value)))) - -(define-widget 'choice 'menu-choice - "A union of several sexp types." - :tag "Choice" - :format "%{%t%}: %[Value Menu%] %v" - :button-prefix 'widget-push-button-prefix - :button-suffix 'widget-push-button-suffix - :prompt-value 'widget-choice-prompt-value) - -(defun widget-choice-prompt-value (widget prompt value unbound) - "Make a choice." - (let ((args (widget-get widget :args)) - (completion-ignore-case (widget-get widget :case-fold)) - current choices old) - ;; Find the first arg that match VALUE. - (let ((look args)) - (while look - (if (widget-apply (car look) :match value) - (setq old (car look) - look nil) - (setq look (cdr look))))) - ;; Find new choice. - (setq current - (cond ((= (length args) 0) - nil) - ((= (length args) 1) - (nth 0 args)) - ((and (= (length args) 2) - (memq old args)) - (if (eq old (nth 0 args)) - (nth 1 args) - (nth 0 args))) - (t - (while args - (setq current (car args) - args (cdr args)) - (setq choices - (cons (cons (widget-apply current :menu-tag-get) - current) - choices))) - (let ((val (completing-read prompt choices nil t))) - (if (stringp val) - (let ((try (try-completion val choices))) - (when (stringp try) - (setq val try)) - (cdr (assoc val choices))) - nil))))) - (if current - (widget-prompt-value current prompt nil t) - value))) - -(define-widget 'radio 'radio-button-choice - "A union of several sexp types." - :tag "Choice" - :format "%{%t%}:\n%v" - :prompt-value 'widget-choice-prompt-value) - -(define-widget 'repeat 'editable-list - "A variable length homogeneous list." - :tag "Repeat" - :format "%{%t%}:\n%v%i\n") - -(define-widget 'set 'checklist - "A list of members from a fixed set." - :tag "Set" - :format "%{%t%}:\n%v") - -(define-widget 'boolean 'toggle - "To be nil or non-nil, that is the question." - :tag "Boolean" - :prompt-value 'widget-boolean-prompt-value - :button-prefix 'widget-push-button-prefix - :button-suffix 'widget-push-button-suffix - :format "%{%t%}: %[Toggle%] %v\n" - :on "on (non-nil)" - :off "off (nil)") - -(defun widget-boolean-prompt-value (widget prompt value unbound) - ;; Toggle a boolean. - (y-or-n-p prompt)) - -;;; The `color' Widget. - -(define-widget 'color 'editable-field - "Choose a color name (with sample)." - :format "%[%t%]: %v (%{sample%})\n" - :size 10 - :tag "Color" - :value "black" - :complete 'widget-color-complete - :sample-face-get 'widget-color-sample-face-get - :notify 'widget-color-notify - :action 'widget-color-action) - -(defun widget-color-complete (widget) - "Complete the color in WIDGET." - (let* ((prefix (buffer-substring-no-properties (widget-field-start widget) - (point))) - (list (widget-color-choice-list)) - (completion (try-completion prefix list))) - (cond ((eq completion t) - (message "Exact match")) - ((null completion) - (error "Can't find completion for \"%s\"" prefix)) - ((not (string-equal prefix completion)) - (insert (substring completion (length prefix)))) - (t - (message "Making completion list...") - (let ((list (all-completions prefix list nil))) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list list))) - (message "Making completion list...done"))))) - -(defun widget-color-sample-face-get (widget) - (or (widget-get widget :sample-face) - (let ((color (widget-value widget)) - (face (make-face (gensym "sample-face-") nil t))) - ;; Use the face object, not its name, to prevent lossage if gc - ;; happens before applying the face. - (widget-put widget :sample-face face) - (and color - (not (equal color "")) - (valid-color-name-p color) - (set-face-foreground face color)) - face))) - -(defvar widget-color-choice-list nil) -;; Variable holding the possible colors. - -(defun widget-color-choice-list () - (or widget-color-choice-list - (setq widget-color-choice-list (read-color-completion-table)))) - -(defvar widget-color-history nil - "History of entered colors") - -(defun widget-color-action (widget &optional event) - ;; Prompt for a color. - (let* ((tag (widget-apply widget :menu-tag-get)) - (answer (read-color (concat tag ": ")))) - (unless (zerop (length answer)) - (widget-value-set widget answer) - (widget-setup) - (widget-apply widget :notify widget event)))) - -(defun widget-color-notify (widget child &optional event) - "Update the sample, and notify the parent." - (let* ((face (widget-apply widget :sample-face-get)) - (color (widget-value widget))) - (if (valid-color-name-p color) - (set-face-foreground face color) - (remove-face-property face 'foreground))) - (widget-default-notify widget child event)) - -;; Is this a misnomer? -(defun widget-at (pos) - "The button or field at POS." - (or (get-char-property pos 'button) - (get-char-property pos 'field))) - -(defun widget-echo-help (pos) - "Display the help echo for widget at POS." - (let* ((widget (widget-at pos)) - (help-echo (and widget (widget-get widget :help-echo)))) - (and (functionp help-echo) - (setq help-echo (funcall help-echo widget))) - (when (stringp help-echo) - (display-message 'no-log help-echo)))) - -;;; The End: - -(provide 'wid-edit) - -;; wid-edit.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/custom/widget.el --- a/lisp/custom/widget.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -;;; widget.el --- a library of user interface components. -;; -;; Copyright (C) 1996, 1997 Free Software Foundation, Inc. -;; -;; Author: Per Abrahamsen -;; Maintainer: Hrvoje Niksic -;; Keywords: help, extensions, faces, hypermedia -;; Version: 1.9960-x -;; X-URL: http://www.dina.kvl.dk/~abraham/custom/ - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; If you want to use this code, please visit the URL above. -;; -;; This file only contain the code needed to define new widget types. -;; Everything else is autoloaded from `wid-edit.el'. - -;;; Code: - -;; Neither XEmacs, nor latest GNU Emacs need this -- provided for -;; compatibility. -;; (defalias 'define-widget-keywords 'ignore) - -(defmacro define-widget-keywords (&rest keys) - "This doesn't do anything in Emacs 20 or XEmacs." - (` - (eval-and-compile - (let ((keywords (quote (, keys)))) - (while keywords - (or (boundp (car keywords)) - (set (car keywords) (car keywords))) - (setq keywords (cdr keywords))))))) - -(defun define-widget (name class doc &rest args) - "Define a new widget type named NAME from CLASS. - -NAME and CLASS should both be symbols, CLASS should be one of the -existing widget types, or nil to create the widget from scratch. - -After the new widget has been defined, the following two calls will -create identical widgets: - -* (widget-create NAME) - -* (apply 'widget-create CLASS ARGS) - -The third argument DOC is a documentation string for the widget." - (put name 'widget-type (cons class args)) - (put name 'widget-documentation doc) - name) - -;;; The End. - -(provide 'widget) - -;; widget.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/derived.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/derived.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,363 @@ +;;; derived.el --- allow inheritance of major modes. + +;; Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. + +;; Author: David Megginson (dmeggins@aix1.uottawa.ca) +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; GNU Emacs is already, in a sense, object oriented -- each object +;; (buffer) belongs to a class (major mode), and that class defines +;; the relationship between messages (input events) and methods +;; (commands) by means of a keymap. +;; +;; The only thing missing is a good scheme of inheritance. It is +;; possible to simulate a single level of inheritance with generous +;; use of hooks and a bit of work -- sgml-mode, for example, also runs +;; the hooks for text-mode, and keymaps can inherit from other keymaps +;; -- but generally, each major mode ends up reinventing the wheel. +;; Ideally, someone should redesign all of Emacs's major modes to +;; follow a more conventional object-oriented system: when defining a +;; new major mode, the user should need only to name the existing mode +;; it is most similar to, then list the (few) differences. +;; +;; In the mean time, this package offers most of the advantages of +;; full inheritance with the existing major modes. The macro +;; `define-derived-mode' allows the user to make a variant of an existing +;; major mode, with its own keymap. The new mode will inherit the key +;; bindings of its parent, and will, in fact, run its parent first +;; every time it is called. For example, the commands +;; +;; (define-derived-mode hypertext-mode text-mode "Hypertext" +;; "Major mode for hypertext.\n\n\\{hypertext-mode-map}" +;; (setq case-fold-search nil)) +;; +;; (define-key hypertext-mode-map [down-mouse-3] 'do-hyper-link) +;; +;; will create a function `hypertext-mode' with its own (sparse) +;; keymap `hypertext-mode-map.' The command M-x hypertext-mode will +;; perform the following actions: +;; +;; - run the command (text-mode) to get its default setup +;; - replace the current keymap with 'hypertext-mode-map,' which will +;; inherit from 'text-mode-map'. +;; - replace the current syntax table with +;; 'hypertext-mode-syntax-table', which will borrow its defaults +;; from the current text-mode-syntax-table. +;; - replace the current abbrev table with +;; 'hypertext-mode-abbrev-table', which will borrow its defaults +;; from the current text-mode-abbrev table +;; - change the mode line to read "Hypertext" +;; - assign the value 'hypertext-mode' to the 'major-mode' variable +;; - run the body of commands provided in the macro -- in this case, +;; set the local variable `case-fold-search' to nil. +;; - **run the command (hypertext-mode-setup), which is empty by +;; default, but may be redefined by the user to contain special +;; commands (ie. setting local variables like 'outline-regexp') +;; **NOTE: do not use this option -- it will soon be obsolete. +;; - run anything assigned to 'hypertext-mode-hooks' (obsolete, but +;; supported for the sake of compatibility). +;; +;; The advantages of this system are threefold. First, text mode is +;; untouched -- if you had added the new keystroke to `text-mode-map,' +;; possibly using hooks, you would have added it to all text buffers +;; -- here, it appears only in hypertext buffers, where it makes +;; sense. Second, it is possible to build even further, and make +;; a derived mode from a derived mode. The commands +;; +;; (define-derived-mode html-mode hypertext-mode "HTML") +;; [various key definitions] +;; +;; will add a new major mode for HTML with very little fuss. +;; +;; Note also the function `derived-mode-class,' which returns the non-derived +;; major mode which a derived mode is based on (ie. NOT necessarily the +;; immediate parent). +;; +;; (derived-mode-class 'text-mode) ==> text-mode +;; (derived-mode-class 'hypertext-mode) ==> text-mode +;; (derived-mode-class 'html-mode) ==> text-mode + +;;; Code: + +;; PUBLIC: define a new major mode which inherits from an existing one. + +;; XEmacs -- no autoload +(defmacro define-derived-mode (child parent name &optional docstring &rest body) + "Create a new mode as a variant of an existing mode. + +The arguments to this command are as follow: + +CHILD: the name of the command for the derived mode. +PARENT: the name of the command for the parent mode (ie. text-mode). +NAME: a string which will appear in the status line (ie. \"Hypertext\") +DOCSTRING: an optional documentation string--if you do not supply one, + the function will attempt to invent something useful. +BODY: forms to execute just before running the + hooks for the new mode. + +Here is how you could define LaTeX-Thesis mode as a variant of LaTeX mode: + + (define-derived-mode LaTeX-thesis-mode LaTeX-mode \"LaTeX-Thesis\") + +You could then make new key bindings for `LaTeX-thesis-mode-map' +without changing regular LaTeX mode. In this example, BODY is empty, +and DOCSTRING is generated by default. + +On a more complicated level, the following command uses sgml-mode as +the parent, and then sets the variable `case-fold-search' to nil: + + (define-derived-mode article-mode sgml-mode \"Article\" + \"Major mode for editing technical articles.\" + (setq case-fold-search nil)) + +Note that if the documentation string had been left out, it would have +been generated automatically, with a reference to the keymap." + + ; Some trickiness, since what + ; appears to be the docstring + ; may really be the first + ; element of the body. + (if (and docstring (not (stringp docstring))) + (progn (setq body (cons docstring body)) + (setq docstring nil))) + (setq docstring (or docstring (derived-mode-make-docstring parent child))) + + (` (progn + (derived-mode-init-mode-variables (quote (, child))) + (defun (, child) () + (, docstring) + (interactive) + ; Run the parent. + ((, parent)) + ; Identify special modes. + (if (get (quote (, parent)) 'special) + (put (quote (, child)) 'special t)) + ;; XEmacs addition + (let ((mode-class (get (quote (, parent)) 'mode-class))) + (if mode-class + (put (quote (, child)) 'mode-class mode-class))) + ; Identify the child mode. + (setq major-mode (quote (, child))) + (setq mode-name (, name)) + ; Set up maps and tables. + (derived-mode-set-keymap (quote (, child))) + (derived-mode-set-syntax-table (quote (, child))) + (derived-mode-set-abbrev-table (quote (, child))) + ; Splice in the body (if any). + (,@ body) +;;; ; Run the setup function, if +;;; ; any -- this will soon be +;;; ; obsolete. +;;; (derived-mode-run-setup-function (quote (, child))) + ; Run the hooks, if any. + (derived-mode-run-hooks (quote (, child))))))) + + +;; PUBLIC: find the ultimate class of a derived mode. + +(defun derived-mode-class (mode) + "Find the class of a major mode. +A mode's class is the first ancestor which is NOT a derived mode. +Use the `derived-mode-parent' property of the symbol to trace backwards." + (while (get mode 'derived-mode-parent) + (setq mode (get mode 'derived-mode-parent))) + mode) + + +;; Inline functions to construct various names from a mode name. + +(defsubst derived-mode-setup-function-name (mode) + "Construct a setup-function name based on a mode name." + (intern (concat (symbol-name mode) "-setup"))) + +(defsubst derived-mode-hooks-name (mode) + "Construct a hooks name based on a mode name." + ;; XEmacs change from -hooks + (intern (concat (symbol-name mode) "-hook"))) + +(defsubst derived-mode-map-name (mode) + "Construct a map name based on a mode name." + (intern (concat (symbol-name mode) "-map"))) + +(defsubst derived-mode-syntax-table-name (mode) + "Construct a syntax-table name based on a mode name." + (intern (concat (symbol-name mode) "-syntax-table"))) + +(defsubst derived-mode-abbrev-table-name (mode) + "Construct an abbrev-table name based on a mode name." + (intern (concat (symbol-name mode) "-abbrev-table"))) + + +;; Utility functions for defining a derived mode. + +;; XEmacs -- don't autoload +(defun derived-mode-init-mode-variables (mode) + "Initialise variables for a new mode. +Right now, if they don't already exist, set up a blank keymap, an +empty syntax table, and an empty abbrev table -- these will be merged +the first time the mode is used." + + (if (boundp (derived-mode-map-name mode)) + t + (eval (` (defvar (, (derived-mode-map-name mode)) + ;; XEmacs change + (make-sparse-keymap (derived-mode-map-name mode)) + (, (format "Keymap for %s." mode))))) + (put (derived-mode-map-name mode) 'derived-mode-unmerged t)) + + (if (boundp (derived-mode-syntax-table-name mode)) + t + (eval (` (defvar (, (derived-mode-syntax-table-name mode)) + ;; XEmacs change + ;; Make a syntax table which doesn't specify anything + ;; for any char. Valid data will be merged in by + ;; derived-mode-merge-syntax-tables. + ;; (make-char-table 'syntax-table nil) + (make-syntax-table) + (, (format "Syntax table for %s." mode))))) + (put (derived-mode-syntax-table-name mode) 'derived-mode-unmerged t)) + + (if (boundp (derived-mode-abbrev-table-name mode)) + t + (eval (` (defvar (, (derived-mode-abbrev-table-name mode)) + (progn (define-abbrev-table (derived-mode-abbrev-table-name mode) nil) + (make-abbrev-table)) + (, (format "Abbrev table for %s." mode))))))) + +(defun derived-mode-make-docstring (parent child) + "Construct a docstring for a new mode if none is provided." + + (format "This major mode is a variant of `%s', created by `define-derived-mode'. +It inherits all of the parent's attributes, but has its own keymap, +abbrev table and syntax table: + + `%s-map' and `%s-syntax-table' + +which more-or-less shadow + + `%s-map' and `%s-syntax-table' + +\\{%s-map}" parent child child parent parent child)) + + +;; Utility functions for running a derived mode. + +(defun derived-mode-set-keymap (mode) + "Set the keymap of the new mode, maybe merging with the parent." + (let* ((map-name (derived-mode-map-name mode)) + (new-map (eval map-name)) + (old-map (current-local-map))) + (and old-map + (get map-name 'derived-mode-unmerged) + (derived-mode-merge-keymaps old-map new-map)) + (put map-name 'derived-mode-unmerged nil) + (use-local-map new-map))) + +(defun derived-mode-set-syntax-table (mode) + "Set the syntax table of the new mode, maybe merging with the parent." + (let* ((table-name (derived-mode-syntax-table-name mode)) + (old-table (syntax-table)) + (new-table (eval table-name))) + (if (get table-name 'derived-mode-unmerged) + (derived-mode-merge-syntax-tables old-table new-table)) + (put table-name 'derived-mode-unmerged nil) + (set-syntax-table new-table))) + +(defun derived-mode-set-abbrev-table (mode) + "Set the abbrev table if it exists. +Always merge its parent into it, since the merge is non-destructive." + (let* ((table-name (derived-mode-abbrev-table-name mode)) + (old-table local-abbrev-table) + (new-table (eval table-name))) + (derived-mode-merge-abbrev-tables old-table new-table) + (setq local-abbrev-table new-table))) + +;;;(defun derived-mode-run-setup-function (mode) +;;; "Run the setup function if it exists." + +;;; (let ((fname (derived-mode-setup-function-name mode))) +;;; (if (fboundp fname) +;;; (funcall fname)))) + +(defun derived-mode-run-hooks (mode) + "Run the hooks if they exist." + + (let ((hooks-name (derived-mode-hooks-name mode))) + (if (boundp hooks-name) + (run-hooks hooks-name)))) + +;; Functions to merge maps and tables. + +(defun derived-mode-merge-keymaps (old new) + "Merge an old keymap into a new one. +The old keymap is set to be the parent of the new one, so that there will +be automatic inheritance." + ;; XEmacs change. FSF 19.30 & 19.34 has a whole bunch of weird crap here + ;; for merging prefix keys and such. Hopefully none of this is + ;; necessary in XEmacs. + (set-keymap-parents new (list old))) + +(defun derived-mode-merge-syntax-tables (old new) + "Merge an old syntax table into a new one. +Where the new table already has an entry, nothing is copied from the old one." + ;; 20.x + (if (fboundp 'map-char-table) + ;; we use map-char-table not map-syntax-table so we can explicitly + ;; check for inheritance. + (map-char-table + #'(lambda (key value) + (if (eq ?@ (char-syntax-from-code value)) + (map-char-table #'(lambda (key1 value1) + (put-char-table key1 value1 new)) + old + key))) + new) + ;; pre-20.0 + (let ((idx 0) + (end (min (length new) (length old)))) + (while (< idx end) + (if (not (aref new idx)) + (aset new idx (aref old idx))) + (setq idx (1+ idx)))))) + +;; Merge an old abbrev table into a new one. +;; This function requires internal knowledge of how abbrev tables work, +;; presuming that they are obarrays with the abbrev as the symbol, the expansion +;; as the value of the symbol, and the hook as the function definition. +(defun derived-mode-merge-abbrev-tables (old new) + (if old + (mapatoms + (function + (lambda (symbol) + (or (intern-soft (symbol-name symbol) new) + (define-abbrev new (symbol-name symbol) + (symbol-value symbol) (symbol-function symbol))))) + old))) + +(provide 'derived) + +;;; derived.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/device.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/device.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,85 @@ +;;; device.el --- miscellaneous device functions not written in C + +;; Copyright (C) 1994-5, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995, 1996 Ben Wing + +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +(defun device-list () + "Return a list of all devices." + (apply 'nconc (mapcar 'console-device-list (console-list)))) + +(defun device-type (&optional device) + "Return the type of the specified device (e.g. `x' or `tty'). +This is equivalent to the type of the device's console. +Value is `tty' for a tty device (a character-only terminal), +`x' for a device that is a screen on an X display, +`ns' for a device that is a NeXTstep connection (not yet implemented), +`w32' for a device that is a Windows or Windows NT connection, +`pc' for a device that is a direct-write MS-DOS screen (not yet implemented), +`stream' for a stream device (which acts like a stdio stream), and +`dead' for a deleted device." + (or device (setq device (selected-device))) + (if (not (device-live-p device)) 'dead + (console-type (device-console device)))) + +(defun make-tty-device (&optional tty terminal-type controlling-process) + "Create a new device on TTY. + TTY should be the name of a tty device file (e.g. \"/dev/ttyp3\" under +SunOS et al.), as returned by the `tty' command. A value of nil means +use the stdin and stdout as passed to XEmacs from the shell. + If TERMINAL-TYPE is non-nil, it should be a string specifying the +type of the terminal attached to the specified tty. If it is nil, +the terminal type will be inferred from the TERM environment variable. + If CONTROLLING-PROCESS is non-nil, it should be an integer +specifying the process id of the process in control of the specified tty. If +it is nil, it is assumes to be the value returned by emacs-pid." + (make-device 'tty tty (list 'terminal-type terminal-type + 'controlling-process controlling-process))) + +(defun make-x-device (&optional display) + "Create a new device connected to DISPLAY." + (make-device 'x display)) + +(defun make-w32-device () + "Create a new win32 device." + (make-device 'w32 nil)) + +(defun device-on-window-system-p (&optional device) + "Return non-nil if DEVICE is on a window system. +This generally means that there is support for the mouse, the menubar, +the toolbar, glyphs, etc." + (or device (setq device (selected-device))) + (console-on-window-system-p (device-console device))) + +(defalias 'valid-device-type-p 'valid-console-type-p) +(defalias 'device-type-list 'console-type-list) +(defalias 'device-pixel-depth 'device-bitplanes) + +;;; device.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/dialog.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/dialog.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,157 @@ +;;; dialog.el --- Dialog-box support for XEmacs + +;; Copyright (C) 1991-4, 1997 Free Software Foundation, Inc. + +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs (when dialog boxes are compiled in). + +;;; Code: +(defun yes-or-no-p-dialog-box (prompt) + "Ask user a \"y or n\" question with a popup dialog box. +Returns t if answer is \"yes\". +Takes one argument, which is the string to display to ask the question." + (let ((echo-keystrokes 0) + event) + (popup-dialog-box + ;; "Non-violent language please!" says Robin. + (cons prompt '(["Yes" yes t] ["No" no t] nil ["Cancel" abort t]))) +; (cons prompt '(["Yes" yes t] ["No" no t] nil ["Abort" abort t]))) + (catch 'ynp-done + (while t + (setq event (next-command-event event)) + (cond ((and (misc-user-event-p event) (eq (event-object event) 'yes)) + (throw 'ynp-done t)) + ((and (misc-user-event-p event) (eq (event-object event) 'no)) + (throw 'ynp-done nil)) + ((and (misc-user-event-p event) + (or (eq (event-object event) 'abort) + (eq (event-object event) 'menu-no-selection-hook))) + (signal 'quit nil)) + ((button-release-event-p event) ;; don't beep twice + nil) + (t + (beep) + (message "please answer the dialog box"))))))) + +(defun yes-or-no-p-maybe-dialog-box (prompt) + "Ask user a yes-or-no question. Return t if answer is yes. +The question is asked with a dialog box or the minibuffer, as appropriate. +Takes one argument, which is the string to display to ask the question. +It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it. +The user must confirm the answer with RET, +and can edit it until it as been confirmed." + (if (should-use-dialog-box-p) + (yes-or-no-p-dialog-box prompt) + (yes-or-no-p-minibuf prompt))) + +(defun y-or-n-p-maybe-dialog-box (prompt) + "Ask user a \"y or n\" question. Return t if answer is \"y\". +Takes one argument, which is the string to display to ask the question. +The question is asked with a dialog box or the minibuffer, as appropriate. +It should end in a space; `y-or-n-p' adds `(y or n) ' to it. +No confirmation of the answer is requested; a single character is enough. +Also accepts Space to mean yes, or Delete to mean no." + (if (should-use-dialog-box-p) + (yes-or-no-p-dialog-box prompt) + (y-or-n-p-minibuf prompt))) + +(if (fboundp 'popup-dialog-box) + (progn + (fset 'yes-or-no-p 'yes-or-no-p-maybe-dialog-box) + (fset 'y-or-n-p 'y-or-n-p-maybe-dialog-box))) + +;; this is call-compatible with the horribly-named FSF Emacs function +;; `x-popup-dialog'. I refuse to use that name. +(defun get-dialog-box-response (position contents) + ;; by Stig@hackvan.com + ;; modified by pez@atlantic2.sbi.com + "Pop up a dialog box and return user's selection. +POSITION specifies which frame to use. +This is normally an event or a window or frame. +If POSITION is t or nil, it means to use the frame the mouse is on. +The dialog box appears in the middle of the specified frame. + +CONTENTS specifies the alternatives to display in the dialog box. +It is a list of the form (TITLE ITEM1 ITEM2...). +Each ITEM is a cons cell (STRING . VALUE). +The return value is VALUE from the chosen item. + +An ITEM may also be just a string--that makes a nonselectable item. +An ITEM may also be nil--that means to put all preceding items +on the left of the dialog box and all following items on the right." + (cond + ((eventp position) + (select-frame (event-frame position))) + ((framep position) + (select-frame position)) + ((windowp position) + (select-window position))) + (let ((dbox (cons (car contents) + (mapcar #'(lambda (x) + (cond + ((null x) + nil) + ((stringp x) + `[,x 'ignore nil]) ;this will never get + ;selected + (t + `[,(car x) (throw 'result ',(cdr x)) t]))) + (cdr contents)) + ))) + (catch 'result + (popup-dialog-box dbox) + (dispatch-event (next-command-event))))) + +(defun message-box (fmt &rest args) + "Display a message, in a dialog box if possible. +If the selected device has no dialog-box support, use the echo area. +The arguments are the same as to `format'. + +If the only argument is nil, clear any existing message; let the +minibuffer contents show." + (if (and (null fmt) (null args)) + (progn + (clear-message nil) + nil) + (let ((str (apply 'format fmt args))) + (if (device-on-window-system-p) + (get-dialog-box-response nil (list str (cons "OK" t))) + (display-message 'message str)) + str))) + +(defun message-or-box (fmt &rest args) + "Display a message in a dialog box or in the echo area.\n\ +If this command was invoked with the mouse, use a dialog box.\n\ +Otherwise, use the echo area. +The arguments are the same as to `format'. + +If the only argument is nil, clear any existing message; let the +minibuffer contents show." + (if (should-use-dialog-box-p) + (apply 'message-box fmt args) + (apply 'message fmt args))) + +;;; dialog.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/disass.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/disass.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,272 @@ +;;; disass.el --- disassembler for compiled Emacs Lisp code + +;;; Copyright (C) 1986, 1991-1994 Free Software Foundation, Inc. + +;; Author: Doug Cutting +;; Jamie Zawinski +;; Maintainer: Jamie Zawinski +;; Keywords: internal + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.28. + +;;; Commentary: + +;; The single entry point, `disassemble', disassembles a code object generated +;; by the Emacs Lisp byte-compiler. This doesn't invert the compilation +;; operation, not by a long shot, but it's useful for debugging. + +;; +;; Original version by Doug Cutting (doug@csli.stanford.edu) +;; Substantially modified by Jamie Zawinski for +;; the new lapcode-based byte compiler. + +;;; Code: + +;;; The variable byte-code-vector is defined by the new bytecomp.el. +;;; The function byte-decompile-lapcode is defined in byte-opt.el. +;;; Since we don't use byte-decompile-lapcode, let's try not loading byte-opt. +;;; The variable byte-code-vector is defined by the new bytecomp.el. +;;; The function byte-decompile-lapcode is defined in byte-optimize.el. +(require 'byte-optimize) + +(defvar disassemble-column-1-indent 8 "*") +(defvar disassemble-column-2-indent 10 "*") +(defvar disassemble-recursive-indent 3 "*") + + +;;;###autoload +(defun disassemble (object &optional buffer indent interactive-p) + "Print disassembled code for OBJECT in (optional) BUFFER. +OBJECT can be a symbol defined as a function, or a function itself +\(a lambda expression or a compiled-function object). +If OBJECT is not already compiled, we compile it, but do not +redefine OBJECT if it is a symbol." + (interactive (list (intern (completing-read "Disassemble function: " + obarray 'fboundp t)) + nil 0 t)) + (if (eq (car-safe object) 'byte-code) + (setq object (list 'lambda () object))) + (or indent (setq indent 0)) ;Default indent to zero + (save-excursion + (if (or interactive-p (null buffer)) + (with-output-to-temp-buffer "*Disassemble*" + (set-buffer "*Disassemble*") + (disassemble-internal object indent (not interactive-p))) + (set-buffer buffer) + (disassemble-internal object indent nil))) + nil) + + +(defun disassemble-internal (obj indent interactive-p) + (let ((macro 'nil) + (name 'nil) + args) + (while (symbolp obj) + (setq name obj + obj (symbol-function obj))) + (if (subrp obj) + (error "Can't disassemble #" name)) + (if (eq (car-safe obj) 'autoload) + (progn + (load (elt obj 1)) + (setq obj (symbol-function name)))) + (if (eq (car-safe obj) 'macro) ;handle macros + (setq macro t + obj (cdr obj))) + (if (and (listp obj) (eq (car obj) 'byte-code)) + (setq obj (list 'lambda nil obj))) + (if (and (listp obj) (not (eq (car obj) 'lambda))) + (error "not a function")) + (if (consp obj) + (if (assq 'byte-code obj) + nil + (if interactive-p (message (if name + "Compiling %s's definition..." + "Compiling definition...") + name)) + (setq obj (byte-compile obj)) + (if interactive-p (message "Done compiling. Disassembling...")))) + (cond ((consp obj) + (setq obj (cdr obj)) ;throw lambda away + (setq args (car obj)) ;save arg list + (setq obj (cdr obj))) + (t + (setq args (compiled-function-arglist obj)))) + (if (zerop indent) ; not a nested function + (progn + (indent-to indent) + (insert (format "byte code%s%s%s:\n" + (if (or macro name) " for" "") + (if macro " macro" "") + (if name (format " %s" name) ""))))) + (let ((doc (if (consp obj) + (and (stringp (car obj)) (car obj)) + (condition-case error + (documentation obj) + (error (format "%S" error)))))) + (if (and doc (stringp doc)) + (progn (and (consp obj) (setq obj (cdr obj))) + (indent-to indent) + (princ " doc: " (current-buffer)) + (let ((frobbed nil)) + (if (string-match "\n" doc) + (setq doc (substring doc 0 (match-beginning 0)) + frobbed t)) + (if (> (length doc) 70) + (setq doc (substring doc 0 65) frobbed t)) + (if frobbed (setq doc (concat doc " ...")))) + (insert doc "\n")))) + (indent-to indent) + (insert " args: ") + (prin1 args (current-buffer)) + (insert "\n") + (if (condition-case () + (commandp obj) ; ie interactivep + (error nil)) + (let ((interactive (if (consp obj) + (elt (assq 'interactive obj) 1) + (elt (compiled-function-interactive obj) 1)))) + (if (eq (car-safe (car-safe obj)) 'interactive) + (setq obj (cdr obj))) + (indent-to indent) + (insert " interactive: ") + (if (eq (car-safe interactive) 'byte-code) + (progn + (insert "\n") + (disassemble-1 interactive + (+ indent disassemble-recursive-indent))) + (let ((print-escape-newlines t)) + (prin1 interactive (current-buffer)))) + (insert "\n"))) + (cond ((and (consp obj) (assq 'byte-code obj)) + (disassemble-1 (assq 'byte-code obj) indent)) + ((compiled-function-p obj) + (disassemble-1 obj indent)) + (t + (insert "Uncompiled body: ") + (let ((print-escape-newlines t)) + (prin1 (if (cdr obj) (cons 'progn obj) (car obj)) + (current-buffer)))))) + (if interactive-p + (message nil))) + + +(defun disassemble-1 (obj indent) + "Prints the byte-code call OBJ in the current buffer. +OBJ should be a call to BYTE-CODE generated by the byte compiler." + (let (bytes constvec) + (if (consp obj) + (setq bytes (car (cdr obj)) ; the byte code + constvec (car (cdr (cdr obj)))) ; constant vector + (setq bytes (compiled-function-instructions obj) + constvec (compiled-function-constants obj))) + (let ((lap (byte-decompile-bytecode bytes constvec)) + op arg opname pc-value) + (let ((tagno 0) + tmp + (lap lap)) + (while (setq tmp (assq 'TAG lap)) + (setcar (cdr tmp) (setq tagno (1+ tagno))) + (setq lap (cdr (memq tmp lap))))) + (while lap + ;; Take off the pc value of the next thing + ;; and put it in pc-value. + (setq pc-value nil) + (if (numberp (car lap)) + (setq pc-value (car lap) + lap (cdr lap))) + ;; Fetch the next op and its arg. + (setq op (car (car lap)) + arg (cdr (car lap))) + (setq lap (cdr lap)) + (indent-to indent) + (if (eq 'TAG op) + (progn + ;; We have a label. Display it, but first its pc value. + (if pc-value + (insert (format "%d:" pc-value))) + (insert (int-to-string (car arg)))) + ;; We have an instruction. Display its pc value first. + (if pc-value + (insert (format "%d" pc-value))) + (indent-to (+ indent disassemble-column-1-indent)) + (if (and op + (string-match "^byte-" (setq opname (symbol-name op)))) + (setq opname (substring opname 5)) + (setq opname "")) + (if (eq op 'byte-constant2) + (insert " #### shouldn't have seen constant2 here!\n ")) + (insert opname) + (indent-to (+ indent disassemble-column-1-indent + disassemble-column-2-indent + -1)) + (insert " ") + (cond ((memq op byte-goto-ops) + (insert (int-to-string (nth 1 arg)))) + ((memq op '(byte-call byte-unbind + byte-listN byte-concatN byte-insertN)) + (insert (int-to-string arg))) + ((memq op '(byte-varref byte-varset byte-varbind)) + (prin1 (car arg) (current-buffer))) + ((memq op '(byte-constant byte-constant2)) + ;; it's a constant + (setq arg (car arg)) + ;; but if the value of the constant is compiled code, then + ;; recursively disassemble it. + (cond ((or (compiled-function-p arg) + (and (eq (car-safe arg) 'lambda) + (assq 'byte-code arg)) + (and (eq (car-safe arg) 'macro) + (or (compiled-function-p (cdr arg)) + (and (eq (car-safe (cdr arg)) 'lambda) + (assq 'byte-code (cdr arg)))))) + (cond ((compiled-function-p arg) + (insert "\n")) + ((eq (car-safe arg) 'lambda) + (insert "")) + (t (insert "\n"))) + (disassemble-internal + arg + (+ indent disassemble-recursive-indent 1) + nil)) + ((eq (car-safe arg) 'byte-code) + (insert "\n") + (disassemble-1 ;recurse on byte-code object + arg + (+ indent disassemble-recursive-indent))) + ((eq (car-safe (car-safe arg)) 'byte-code) + (insert "(...)\n") + (mapcar ;recurse on list of byte-code objects + '(lambda (obj) + (disassemble-1 + obj + (+ indent disassemble-recursive-indent))) + arg)) + (t + ;; really just a constant + (let ((print-escape-newlines t)) + (prin1 arg (current-buffer)))))) + ) + (insert "\n"))))) + nil) + +(provide 'disass) + +;;; disass.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/easymenu.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/easymenu.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,217 @@ +;;; easymenu.el - Easy menu support for Emacs 19 and XEmacs. + +;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +;; Author: Per Abrahamsen +;; Maintainer: XEmacs Development Team +;; Keywords: internal, extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Not synched with FSF. + +;; Commentary: + +;; This file is dumped with XEmacs. + +;; Easymenu allows you to define menus for both Emacs 19 and XEmacs. + +;; This file +;; The advantages of using easymenu are: + +;; - Easier to use than either the Emacs 19 and XEmacs menu syntax. + +;; - Common interface for Emacs 18, Emacs 19, and XEmacs. +;; (The code does nothing when run under Emacs 18). + +;; The public functions are: + +;; - Function: easy-menu-define SYMBOL MAPS DOC MENU +;; SYMBOL is both the name of the variable that holds the menu and +;; the name of a function that will present a the menu. +;; MAPS is a list of keymaps where the menu should appear in the menubar. +;; DOC is the documentation string for the variable. +;; MENU is an XEmacs style menu description. + +;; See the documentation for easy-menu-define for details. + +;; - Function: easy-menu-change PATH NAME ITEMS +;; Change an existing menu. +;; The menu must already exist and be visible on the menu bar. +;; PATH is a list of strings used for locating the menu on the menu bar. +;; NAME is the name of the menu. +;; ITEMS is a list of menu items, as defined in `easy-menu-define'. + +;; - Function: easy-menu-add MENU [ MAP ] +;; Add MENU to the current menubar in MAP. + +;; - Function: easy-menu-remove MENU +;; Remove MENU from the current menubar. + +;; Emacs 19 never uses `easy-menu-add' or `easy-menu-remove', menus +;; automatically appear and disappear when the keymaps specified by +;; the MAPS argument to `easy-menu-define' are activated. + +;; XEmacs will bind the map to button3 in each MAPS, but you must +;; explicitly call `easy-menu-add' and `easy-menu-remove' to add and +;; remove menus from the menu bar. + +;;; Code: + +;; ;;;###autoload +(defmacro easy-menu-define (symbol maps doc menu) + "Define a menu bar submenu in maps MAPS, according to MENU. +The arguments SYMBOL and DOC are ignored; they are present for +compatibility only. SYMBOL is not evaluated. In other Emacs versions +these arguments may be used as a variable to hold the menu data, and a +doc string for that variable. + +The first element of MENU must be a string. It is the menu bar item name. +The rest of the elements are menu items. + +A menu item is usually a vector of three elements: [NAME CALLBACK ENABLE] + +NAME is a string--the menu item name. + +CALLBACK is a command to run when the item is chosen, +or a list to evaluate when the item is chosen. + +ENABLE is an expression; the item is enabled for selection +whenever this expression's value is non-nil. + +Alternatively, a menu item may have the form: + + [ NAME CALLBACK [ KEYWORD ARG ] ... ] + +Where KEYWORD is one of the symbol defined below. + + :keys KEYS + +KEYS is a string; a complex keyboard equivalent to this menu item. + + :active ENABLE + +ENABLE is an expression; the item is enabled for selection +whenever this expression's value is non-nil. + + :suffix NAME + +NAME is a string; the name of an argument to CALLBACK. + + :style STYLE + +STYLE is a symbol describing the type of menu item. The following are +defined: + +toggle: A checkbox. + Currently just prepend the name with the string \"Toggle \". +radio: A radio button. +nil: An ordinary menu item. + + :selected SELECTED + +SELECTED is an expression; the checkbox or radio button is selected +whenever this expression's value is non-nil. +Currently just disable radio buttons, no effect on checkboxes. + +A menu item can be a string. Then that string appears in the menu as +unselectable text. A string consisting solely of hyphens is displayed +as a solid horizontal line. + +A menu item can be a list. It is treated as a submenu. +The first element should be the submenu name. That's used as the +menu item in the top-level menu. The cdr of the submenu list +is a list of menu items, as above." + (` (progn + (defvar (, symbol) nil (, doc)) + (easy-menu-do-define (quote (, symbol)) (, maps) (, doc) (, menu))))) + +(defun easy-menu-do-define (symbol maps doc menu) + (if (featurep 'menubar) + (progn + (set symbol menu) + (fset symbol (list 'lambda '(e) + doc + '(interactive "@e") + '(run-hooks 'activate-menubar-hook) + '(setq zmacs-region-stays 't) + (list 'popup-menu symbol)))))) + +(defun easy-menu-change (&rest args) + (when (featurep 'menubar) + (apply 'add-menu args))) + +;; This variable hold the easy-menu mode menus of all major and +;; minor modes currently in effect in the current buffer. +(defvar easy-menu-all-popups nil) +(make-variable-buffer-local 'easy-menu-all-popups) + +(defun easy-menu-add (menu &optional map) + "Add MENU to the current menu bar." + (if (featurep 'menubar) + (progn + (unless (member menu easy-menu-all-popups) + (push menu easy-menu-all-popups)) + (setq mode-popup-menu (if (> (length easy-menu-all-popups) 1) + (cons (easy-menu-title) + (reverse easy-menu-all-popups)) + (car easy-menu-all-popups))) + + (cond ((null current-menubar) + ;; Don't add it to a non-existing menubar. + nil) + ((assoc (car menu) current-menubar) + ;; Already present. + nil) + ((equal current-menubar '(nil)) + ;; Set at left if only contains right marker. + (set-buffer-menubar (list menu nil))) + (t + ;; Add at right. + (set-buffer-menubar (copy-sequence current-menubar)) + (add-menu nil (car menu) (cdr menu))))))) + +(defun easy-menu-remove (menu) + "Remove MENU from the current menu bar." + (if (featurep 'menubar) + (progn + (setq easy-menu-all-popups (delq menu easy-menu-all-popups) + mode-popup-menu (if (< (length easy-menu-all-popups) 1) + (cons (easy-menu-title) + (reverse easy-menu-all-popups)) + (car easy-menu-all-popups))) + + (and current-menubar + (assoc (car menu) current-menubar) + (delete-menu-item (list (car menu))))))) + +;; Think up a good title for the menu. Take the major-mode of the +;; buffer, strip the -mode part, convert hyphens to spaces, and +;; capitalize it. +;; +;; If you can think of something smarter, feel free to replace it. +;; Don't forget to mail the change to xemacs@xemacs.org where everyone +;; can flame, er, praise your changes. +(defun easy-menu-title () + (capitalize (replace-in-string (replace-in-string + (symbol-name major-mode) "-mode$" "") + "-" " "))) + +(provide 'easymenu) + +;;; easymenu.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/Makefile --- a/lisp/edebug/Makefile Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -# Makefile for the edebug manual, and distribution packaging. -# -# March 1994 - -# The version of edebug. -VERSION = 3.4 - -# Redefine `TEX' if `tex' does not invoke plain TeX. For example: -# TEX=platex -TEX=tex - -# Redefine `DVIPS' if it is not `dvips'. The command line may need -# to be changed anyway. -DVIPS=dvips - -FILES = README Makefile edebug.el cust-print.el edebug-history \ - eval-region.el \ - edebug-test.el \ - cl-specs.el cl-read.el edebug-cl-read.el \ - edebug.tex edebug.texi - -# I include the cl package for now. -CLFILES = cl.el cl-extra.el cl-macs.el cl-seq.el cl-compat.el cl.texinfo - -SUBDIR = edebug-${VERSION} - -all: edebug.dvi - -# First shot to define xrefs and produce permuted index. -edebug.cp: edebug.tex edebug.texi - $(TEX) edebug.tex - -edebug.cps: edebug.cp - ./permute-index edebug cp - mv permuted.cps edebug.cps - -# Produce the final dvi. -edebug.dvi: edebug.cps - $(TEX) edebug.tex # This modifies edebug.cp again. - touch edebug.cps # This one is OK. - -# Produce a postscript file -edebug.ps: edebug.dvi - $(DVIPS) edebug.dvi -o edebug.ps - -# Produce edebug.info -edebug.info: edebug.tex edebug.texi - makeinfo edebug.tex - -dist edebug.tar.Z: ${FILES} - rm -rf edebug.tar edebug.tar.Z ${SUBDIR} - mkdir ${SUBDIR} - mv ${FILES} ${SUBDIR} - tar chf edebug.tar ${SUBDIR} - mv ${SUBDIR}/* . - compress edebug.tar - rm -r ${SUBDIR} - -cl-dist: ${CLFILES} - rm -rf cl.tar cl.tar.Z - tar cf cl.tar ${CLFILES} - compress cl.tar - -unpack: - uncompress edebug.tar.Z - tar xf edebug.tar - -mostlyclean clean: - rm -f edebug.dvi edebug.log edebug.toc - rm -f edebug.cp edebug.fn edebug.ky edebug.pg edebug.tp edebug.vr - rm -rf edebug.tar edebug.tar.Z ${SUBDIR} - -distclean realclean: clean - rm -f edebug.??s edebug.aux # tex files - rm -f *.elc diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/README --- a/lisp/edebug/README Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -Files included in this distribution: - -README This file. -Makefile Just enough to make the manual and distribution. -edebug.el The reason for all this. -cust-print.el The custom print package. -edebug-history A history of older modifications. -eval-reg.el Elisp version of eval-region. -cl-specs.el Specifications for Common Lisp macros. -cl-read.el Customizable, CL-like reader from bosch@crpht.lu. -edebug-cl-read.el Edebug reader macros for use with cl-read. -edebug.tex The manual source. -edebug.texi The core of the manual for Lisp Reference Manual. -edebug-test.el Some tests, not organized. - --------------------------- -Installation - -To install, put the .el files in some directory in your load-path and -byte-compile them. Put the following forms in your .emacs file. - -(define-key emacs-lisp-mode-map "\C-xx" 'edebug-eval-top-level-form) -(autoload 'edebug-eval-top-level-form "edebug") - -If you wish to change the default edebug global command prefix, change this: -(setq edebug-global-prefix "\C-xX") - -Other options, are described in the manual. -Also see cl-specs.el, and edebug-cl-read.el if they apply to you. - -In previous versions of edebug, users were directed to set -`debugger' to `edebug-debug'. This is no longer necessary -since Edebug automatically sets it whenever Edebug is active. - ---------------------------- - -Send me your enhancements, ideas, bugs, or fixes. -There is an edebug mailing list if you want to keep up -with the latest developments: edebug@cs.uiuc.edu -(requests to: edebug-request@cs.uiuc.edu) - -You can use edebug-submit-bug-report to simplify bug reporting. - -Daniel LaLiberte 217-398-4114 -University of Illinois, Urbana-Champaign -Department of Computer Science - -704 W Green -Champaign IL, 61820 diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/advise-eval-region.el --- a/lisp/edebug/advise-eval-region.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -;;; advise-eval-region.el --- Wrap advice around eval-region -;; Copyright (C) 1996 Miranova Systems, Inc. - -;; Original-Author: Unknown -;; Adapted-By: Steven L Baur -;; Keywords: extensions lisp - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF. - -;;; Commentary: - -;; This file splits out advice to eval-region formerly done in cl-read.el. -;; Due to the way cl-read.el reads itself in twice during bytecompilation, -;; and the fact that functions shouldn't be advised twice, I split this out -;; into its own file. - -;;; Code: - -(require 'advice) - -;; Advise the redefined eval-region -(defadvice eval-region (around cl-read activate) - "Use the reader::read instead of the original read if cl-read-active." - (with-elisp-eval-region (not cl-read-active) - ad-do-it)) - -(provide 'advise-eval-region) - -;;; advise-eval-region.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/auto-autoloads.el --- a/lisp/edebug/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'edebug-autoloads) (error "Already loaded")) - -;;;### (autoloads (edebug-eval-top-level-form def-edebug-spec) "edebug" "edebug/edebug.el") - -(autoload 'def-edebug-spec "edebug" "\ -Set the edebug-form-spec property of SYMBOL according to SPEC. -Both SYMBOL and SPEC are unevaluated. The SPEC can be 0, t, a symbol -\(naming a function), or a list." nil 'macro) - -(defalias 'edebug-defun 'edebug-eval-top-level-form) - -(autoload 'edebug-eval-top-level-form "edebug" "\ -Evaluate a top level form, such as a defun or defmacro. -This is like `eval-defun', but the code is always instrumented for Edebug. -Print its name in the minibuffer and leave point where it is, -or if an error occurs, leave point after it with mark at the original point." t nil) - -;;;*** - -(provide 'edebug-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/cl-read.el --- a/lisp/edebug/cl-read.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1401 +0,0 @@ -;; Customizable, Common Lisp like reader for Emacs Lisp. -;; -;; Copyright (C) 1993 by Guido Bosch - -;; This file is part of XEmacs - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; Please send bugs and comments to the author. -;; -;; -;; This program is still under development. Neither the author nor -;; his employer accepts responsibility to anyone for the consequences of -;; using it or for whether it serves any particular purpose or works -;; at all. - - -;; Introduction -;; ------------ -;; -;; This package replaces the standard Emacs Lisp reader (implemented -;; as a set of built-in Lisp function in C) by a flexible and -;; customizable Common Lisp like one (implemented entirely in Emacs -;; Lisp). During reading of Emacs Lisp source files, it is about 40% -;; slower than the built-in reader, but there is no difference in -;; loading byte compiled files - they dont contain any syntactic sugar -;; and are loaded with the built in subroutine `load'. -;; -;; The user level functions for defining read tables, character and -;; dispatch macros are implemented according to the Commom Lisp -;; specification by Steel's (2nd edition), but the read macro functions -;; themselves are implemented in a slightly different way, because the -;; basic character reading is done in an Emacs buffer, and not by -;; using the primitive functions `read-char' and `unread-char', as real -;; CL does. To get 100% compatibility with CL, the above functions -;; (or their equivalents) must be implemented as subroutines. -;; -;; Another difference with real CL reading is that basic tokens (symbols -;; numbers, strings, and a few more) are still read by the original -;; built-in reader. This is necessary to get reasonable performance. -;; As a consquence, the read syntax of basic tokens can't be -;; customized. - -;; Most of the built-in reader syntax has been replaced by lisp -;; character macros: parentheses and brackets, simple and double -;; quotes, semicolon comments and the dot. In addition to that, the -;; following new syntax features are provided: - -;; Backquote-Comma-Atsign Macro: `(,el ,@list) -;; -;; (the clumsy Emacs Lisp syntax (` ((, el) (,@ list))) is also -;; supported, but with one restriction: the blank behind the quote -;; characters is mandatory when using the old syntax. The cl reader -;; needs it as a landmark to distinguish between old and new syntax. -;; An example: -;; -;; With blanks, both readers read the same: -;; (` (, (head)) (,@ (tail))) -std-read-> (` (, (head)) (,@ (tail))) -;; (` (, (head)) (,@ (tail))) -cl-read-> (` (, (head)) (,@ (tail))) -;; -;; Without blanks, the form is interpreted differently by the two readers: -;; (`(,(head)) (,@(tail))) -std-read-> (` (, (head)) (,@ (tail))) -;; (`(,(head)) (,@(tail))) -cl-read-> ((` ((, ((head)))) ((,@ ((tail))))) -;; -;; -;; Dispatch Character Macro" `#' -;; -;; #' function quoting -;; #\ character syntax -;; #.
read time evaluation -;; #p, #P paths -;; #+, #- conditional reading -;; #=, ## tags for shared structure reading -;; -;; Other read macros can be added easily (see the definition of the -;; above ones in this file, using the functions `set-macro-character' -;; and `set-dispatch-macro-character') -;; -;; The Cl reader is mostly downward compatile, (exception: backquote -;; comma macro, see above). E.g., this file, which is written entirely -;; in the standard Emacs Lisp syntax, can be read and compiled with the -;; cl-reader activated (see Examples below). - -;; This also works with package.el for Common Lisp packages. - - -;; Requirements -;; ------------ -;; The package runs on Emacs 18 and Emacs 19 (FSF and Lucid) It is -;; built on top of Dave Gillespie's cl.el package (version 2.02 or -;; later). The old one (from Ceazar Quiroz, still shiped with some -;; Emacs 19 disributions) will not do. - -;; Usage -;; ----- -;; The package is implemented as a kind of minor mode to the -;; emacs-lisp-mode. As most of the Emacs Lisp files are still written -;; in the standard Emacs Lisp syntax, the cl reader is only activated -;; on elisp files whose property lines contain the following entry: -;; -;; -*- Read-Syntax: Common-Lisp -*- -;; -;; Note that both property name ("Read-Syntax") and value -;; ("Common-Lisp") are not case sensitive. There can also be other -;; properties in this line: -;; -;; -*- Mode: Emacs-Lisp; Read-Syntax: Common-Lisp -*- - -;; Installation -;; ------------ -;; Save this file in a directory where Emacs will find it, then -;; byte compile it (M-x byte-compile-file). -;; -;; A permanent installation of the package can be done in two ways: -;; -;; 1.) If you want to have the package always loaded, put this in your -;; .emacs, or in just the files that require it: -;; -;; (require 'cl-read) -;; -;; 2.) To load the cl-read package automatically when visiting an elisp -;; file that needs it, it has to be installed using the -;; emacs-lisp-mode-hook. In this case, put the following function -;; definition and add-hook form in your .emacs: -;; -;; (defun cl-reader-autoinstall-function () -;; "Activates the Common Lisp style reader for emacs-lisp-mode buffers, -;; if the property line has a local variable setting like this: -;; \;\; -*- Read-Syntax: Common-Lisp -*-" -;; -;; (or (boundp 'local-variable-hack-done) -;; (let (local-variable-hack-done -;; (case-fold-search t)) -;; (hack-local-variables-prop-line 't) -;; (cond -;; ((and (boundp 'read-syntax) -;; read-syntax -;; (string-match "^common-lisp$" (symbol-name read-syntax))) -;; (require 'cl-read) -;; (make-local-variable 'cl-read-active) -;; (setq cl-read-active 't)))))) -;; -;; (add-hook 'emacs-lisp-mode-hook 'cl-reader-autoinstall-function) -;; -;; The `cl-reader-autoinstall-function' function tests for the -;; presence of the correct Read-Syntax property in the first line of -;; the file and loads the cl-read package if necessary. cl-read -;; replaces the following standard elisp functions: -;; -;; - read -;; - read-from-string -;; - eval-current-buffer -;; - eval-buffer -;; - eval-region -;; - eval-expression (to call reader explicitly) -;; -;; There may be other built-in functions that need to be replaced -;; (e.g. load). The behavior of the new reader function depends on -;; the value of the buffer local variable `cl-read-active': if it is -;; nil, they just call the original functions, otherwise they call the -;; cl reader. If the cl reader is active in a buffer, this is -;; indicated in the modeline by the string "CL" (minor mode like). -;; - -;; Examples: -;; --------- -;; After having installed the package as described above, the -;; following forms can be evaluated (M-C-x) with the cl reader being -;; active. (make sure that the mode line displays "(Emacs-Lisp CL)") -;; -;; (setq whitespaces '(#\space #\newline #\tab)) -;; (setq more-whitespaces `(#\page ,@whitespaces #\linefeed)) -;; (setq whitespace-strings (mapcar #'char-to-string more-whitespaces)) -;; -;; (setq shared-struct '(#1=[hello world] #1# #1#)) -;; (progn (setq cirlist '#1=(a b . #1#)) 't) -;; -;; This file, though written in standard Emacs Lisp syntax, can also be -;; compiled with the cl reader active: Type M-x byte-compile-file - -;; TO DO List: -;; ----------- -;; - Provide a replacement for load so that uncompiled cl syntax -;; source file can be loaded, too. For now prohibit loading un-bytecompiled. -;; - Do we really need the (require 'cl) dependency? Yes. -;; - More read macros: #S for structs, #A for array, #X for hex, #nR for radix -;; - Refine the error signaling mechanism. -;; - invalid-cl-read-syntax is now defined. what else? - - -; Change History -; -; $Log: cl-read.el,v $ -; Revision 1.2 1997/03/08 23:25:50 steve -; Patches to Beta6 -; -; Revision 1.19 94/03/21 19:59:24 liberte -; Add invalid-cl-read-syntax error symbol. -; Add reader::read-sexp and reader::read-sexp-func to allow customization -; based on the results of reading. -; Remove more dependencies on cl-package. -; Remove reader::eval-current-buffer, eval-buffer, and eval-region, -; and use elisp-eval-region package instead. -; -; Revision 1.18 94/03/04 23:42:24 liberte -; Fix typos in comments. -; -; Revision 1.17 93/11/24 12:04:09 bosch -; cl-packages dependency removed. `reader::read-constituent' and -; corresponding variables moved to cl-packages.el. -; Multi-line comment #| ... |# dispatch character read macro added. -; -; Revision 1.16 1993/11/23 10:21:02 bosch -; Patches from Daniel LaLiberte integrated. -; -; Revision 1.15 1993/11/18 21:21:10 bosch -; `reader::symbol-regexp1' modified. -; -; Revision 1.14 1993/11/17 19:06:32 bosch -; More characters added to `reader::symbol-characters'. -; `reader::read-constituent' modified. -; defpackage form added. -; -; Revision 1.13 1993/11/16 13:06:41 bosch -; - Symbol reading for CL package convention implemented. -; Variables `reader::symbol-characters', `reader::symbol-regexp1' and -; `reader::symbol-regexp2' and functions `reader::lookup-symbol' and -; `reader::read-constituent' added. -; - Prefix for internal symbols is now "reader::" (Common Lisp -; compatible). -; - Dispatch character macro #: for reading uninterned symbols added. -; -; Revision 1.12 1993/11/07 19:29:07 bosch -; Minor bug fix. -; -; Revision 1.11 1993/11/07 19:23:59 bosch -; Comment added. Character read macro #\ rewritten. Now reads -; e.g. #\meta-control-x. Needs to be checked. -; fix in `reader::restore-shared-structure'. `cl-reader-autoinstall-function' improved. -; -; Revision 1.10 1993/11/06 18:35:35 bosch -; Included Daniel LaLiberte's Patches. -; Efficiency of `reader::restore-shared-structure' improved. -; Implementation notes for shared structure reading added. -; -; Revision 1.9 1993/09/08 07:44:54 bosch -; Comment modified. -; -; Revision 1.8 1993/08/10 13:43:34 bosch -; Hook function `cl-reader-autoinstall-function' for automatic installation added. -; Buffer local variable `cl-read-active' added: together with the above -; hook it allows the file specific activation of the cl reader. -; -; Revision 1.7 1993/08/10 10:35:21 bosch -; Functions `read*' and `read-from-string*' renamed into `reader::read' -; and `reader::read-from-string'. Whitespace character skipping after -; recursive reader calls removed (Emacs 19 should not need this). -; Functions `cl-reader-install' and `cl-reader-uninstall' updated. -; Introduction text and function comments added. -; -; Revision 1.6 1993/08/09 15:36:05 bosch Function `read*' now nearly -; elisp compatible (no functions as streams, yet -- I don't think I -; will ever implement this, it would be far too slow). Elisp -; compatible function `read-from-string*' added. Replacements for -; `eval-current-buffer', `eval-buffer' and `eval-region' added. -; Renamed feature `cl-dg' in `cl', as Dave Gillespie's cl.el package -; is rather stable now. Function `cl-reader-install' and -; `cl-reader-uninstall' modified. -; -; Revision 1.5 1993/08/09 10:23:35 bosch -; Functions `copy-readtable' and `set-syntax-from-character' added. -; Variable `reader::internal-standard-readtable' added. Standard -; readtable initialization modified. Whitespace skipping placed back -; inside the read loop. -; -; Revision 1.4 1993/05/14 13:00:48 bosch -; Included patches from Daniel LaLiberte. -; -; Revision 1.3 1993/05/11 09:57:39 bosch -; `read*' renamed in `reader::read-from-buffer'. `read*' now can read -; from strings. -; -; Revision 1.2 1993/05/09 16:30:50 bosch -; (require 'cl-read) added. -; Calling of `{before,after}-read-hook' modified. -; -; Revision 1.1 1993/03/29 19:37:21 bosch -; Initial revision -; -; - -;;; Code: - -(require 'cl) -;; Thou shalt evaluate a defadvice only once, or thou shalt surely lose. -sb -(require 'advise-eval-region) - -;; load before compiling -;; This is ugly, but apparently the only way to do it :-( -sb -(provide 'cl-read) -(require 'cl-read) - -;; bootstrapping with cl-packages -;; defpackage and in-package are ignored until cl-read is installed. -'(defpackage reader - (:nicknames "rd") - (:use el) - (:export - cl-read-active - copy-readtable - set-macro-character - get-macro-character - set-syntax-from-character - make-dispatch-macro-character - set-dispatch-macro-character - get-dispatch-macro-character - before-read-hook - after-read-hook - cl-reader-install - cl-reader-uninstall - read-syntax - cl-reader-autoinstall-function)) - -'(in-package reader) - - -(autoload 'compiled-function-p "bytecomp") - -;; This makes cl-read behave as a kind of minor mode: - -(make-variable-buffer-local 'cl-read-active) -(defvar cl-read-active nil - "Buffer local variable that enables Common Lisp style syntax reading.") -(setq-default cl-read-active nil) - -(or (assq 'cl-read-active minor-mode-alist) - (setq minor-mode-alist - (cons '(cl-read-active " CL") minor-mode-alist))) - -;; Define a new error symbol: invalid-cl-read-syntax -;; XEmacs change -(define-error 'invalid-cl-read-syntax "Invalid CL read syntax" - 'invalid-read-syntax) - -(defun reader::error (msg &rest args) - (signal 'invalid-cl-read-syntax (list (apply 'format msg args)))) - - -;; The readtable - -(defvar reader::readtable-size 256 - "The size of a readtable." - ;; Actually, the readtable is a vector of size (1+ - ;; reader::readtable-size), because the last element contains the - ;; symbol `readtable', used for defining `readtablep. - ) - -;; An entry of the readtable must have one of the following forms: -;; -;; 1. A symbol, one of {illegal, constituent, whitespace}. It means -;; the character's reader class. -;; -;; 2. A function (i.e., a symbol with a function definition, a byte -;; compiled function or an uncompiled lambda expression). It means the -;; character is a macro character. -;; -;; 3. A vector of length `reader::readtable-size'. Elements of this vector -;; may be `nil' or a function (see 2.). It means the character is a -;; dispatch character, and the vector its dispatch function table. - -(defvar *readtable*) -(defvar reader::internal-standard-readtable) - -(defun* copy-readtable - (&optional (from-readtable *readtable*) - (to-readtable - (make-vector (1+ reader::readtable-size) 'illegal))) - "Return a copy of FROM-READTABLE \(default: *readtable*\). If the -FROM-READTABLE argument is provided as `nil', make a copy of a -standard \(CL-like\) readtable. If TO-READTABLE is provided, modify and -return it, otherwise create a new readtable object." - - (if (null from-readtable) - (setq from-readtable reader::internal-standard-readtable)) - - (loop for i to reader::readtable-size - as from-syntax = (aref from-readtable i) - do (setf (aref to-readtable i) - (if (vectorp from-syntax) - (copy-sequence from-syntax) - from-syntax)) - finally return to-readtable)) - - -(defmacro reader::get-readtable-entry (char readtable) - (` (aref (, readtable) (, char)))) - -(defun set-macro-character - (char function &optional readtable) - "Makes CHAR to be a macro character with FUNCTION as handler. -When CHAR is seen by reader::read-from-buffer, it calls FUNCTION. -Returns always t. Optional argument READTABLE is the readtable to set -the macro character in (default: *readtable*)." - (or readtable (setq readtable *readtable*)) - (or (reader::functionp function) - (reader::error "Not valid character macro function: %s" function)) - (setf (reader::get-readtable-entry char readtable) function) - t) - - -(put 'set-macro-character 'edebug-form-spec - '(&define sexp function-form &optional sexp)) -(put 'set-macro-character 'lisp-indent-function 1) - -(defun get-macro-character (char &optional readtable) - "Return the function associated with the character CHAR. -Optional READTABLE defaults to *readtable*. If char isn't a macro -character in READTABLE, return nil." - (or readtable (setq readtable *readtable*)) - (let ((entry (reader::get-readtable-entry char readtable))) - (if (reader::functionp entry) - entry))) - -(defun set-syntax-from-character - (to-char from-char &optional to-readtable from-readtable) - "Make the syntax of TO-CHAR be the same as the syntax of FROM-CHAR. -Optional TO-READTABLE and FROM-READTABLE are the corresponding tables -to use. TO-READTABLE defaults to the current readtable -\(*readtable*\), and FROM-READTABLE to nil, meaning to use the -syntaxes from the standard Lisp Readtable." - (or to-readtable (setq to-readtable *readtable*)) - (or from-readtable - (setq from-readtable reader::internal-standard-readtable)) - (let ((from-syntax - (reader::get-readtable-entry from-char from-readtable))) - (if (vectorp from-syntax) - ;; dispatch macro character table - (setq from-syntax (copy-sequence from-syntax))) - (setf (reader::get-readtable-entry to-char to-readtable) - from-syntax)) - t) - - -;; Dispatch macro character -(defun make-dispatch-macro-character (char &optional readtable) - "Let CHAR be a dispatch macro character in READTABLE (default: *readtable*)." - (or readtable (setq readtable *readtable*)) - (setf (reader::get-readtable-entry char readtable) - ;; create a dispatch character table - (make-vector reader::readtable-size nil))) - - -(defun set-dispatch-macro-character - (disp-char sub-char function &optional readtable) - "Make reading CHAR1 followed by CHAR2 be handled by FUNCTION. -Optional argument READTABLE (default: *readtable*). CHAR1 must first be -made a dispatch char with `make-dispatch-macro-character'." - (or readtable (setq readtable *readtable*)) - (let ((disp-table (reader::get-readtable-entry disp-char readtable))) - ;; check whether disp-char is a valid dispatch character - (or (vectorp disp-table) - (reader::error "`%c' not a dispatch macro character." disp-char)) - ;; check whether function is a valid function - (or (reader::functionp function) - (reader::error "Not valid dispatch character macro function: %s" - function)) - (setf (aref disp-table sub-char) function))) - -(put 'set-dispatch-macro-character 'edebug-form-spec - '(&define sexp sexp function-form &optional sexp)) -(put 'set-dispatch-macro-character 'lisp-indent-function 2) - - -(defun get-dispatch-macro-character - (disp-char sub-char &optional readtable) - "Return the macro character function for SUB-CHAR unser DISP-CHAR. -Optional READTABLE defaults to *readtable*. -Returns nil if there is no such function." - (or readtable (setq readtable *readtable*)) - (let ((disp-table (reader::get-readtable-entry disp-char readtable))) - (and (vectorp disp-table) - (reader::functionp (aref disp-table sub-char)) - (aref disp-table sub-char)))) - - -(defun reader::functionp (function) - ;; Check whether FUNCTION is a valid function object to be used - ;; as (dispatch) macro character function. - (or (and (symbolp function) (fboundp function)) - (compiled-function-p function) - (and (consp function) (eq (first function) 'lambda)))) - - -;; The basic reader loop - -;; shared and circular structure reading -(defvar reader::shared-structure-references nil) -(defvar reader::shared-structure-labels nil) - -(defun reader::read-sexp-func (point func) - ;; This function is called to read a sexp at POINT by calling FUNC. - ;; reader::read-sexp-func is here to be advised, e.g. by Edebug, - ;; to do something before or after reading. - (funcall func)) - -(defmacro reader::read-sexp (point &rest body) - ;; Called to return a sexp starting at POINT. BODY creates the sexp result - ;; and should leave point after the sexp. The body is wrapped in - ;; a lambda expression and passed to reader::read-sexp-func. - (` (reader::read-sexp-func (, point) (function (lambda () (,@ body)))))) - -(put 'reader::read-sexp 'edebug-form-spec '(form body)) -(put 'reader::read-sexp 'lisp-indent-function 2) -(put 'reader::read-sexp 'lisp-indent-hook 1) ;; Emacs 18 - - -(defconst before-read-hook nil) -(defconst after-read-hook nil) - -;; Set the hooks to `read-char' in order to step through the reader. e.g. -;; (add-hook 'before-read-hook '(lambda () (message "before") (read-char))) -;; (add-hook 'after-read-hook '(lambda () (message "after") (read-char))) - -(defmacro reader::encapsulate-recursive-call (reader-call) - ;; Encapsulate READER-CALL, a form that contains a recursive call to - ;; the reader, for usage inside the main reader loop. The macro - ;; wraps two hooks around READER-CALL: `before-read-hook' and - ;; `after-read-hook'. - ;; - ;; If READER-CALL returns normally, the macro exits immediately from - ;; the surrounding loop with the value of READER-CALL as result. If - ;; it exits non-locally (with tag `reader-ignore'), it just returns - ;; the value of READER-CALL, in which case the surrounding reader - ;; loop continues its execution. - ;; - ;; In both cases, `before-read-hook' and `after-read-hook' are - ;; called before and after executing READER-CALL. - ;; Are there any other uses for these hooks? Edebug doesn't need them. - (` (prog2 - (run-hooks 'before-read-hook) - ;; this catch allows to ignore the return, in the case that - ;; reader::read-from-buffer should continue looping (e.g. - ;; skipping over comments) - (catch 'reader-ignore - ;; this only works inside a block (e.g., in a loop): - ;; go outside - (return - (prog1 - (, reader-call) - ;; this occurrence of the after hook fires if the - ;; reader-call returns normally ... - (run-hooks 'after-read-hook)))) - ;; ... and that one if it was thrown to the tag 'reader-ignore - (run-hooks 'after-read-hook)))) - -(put 'reader::encapsulate-recursive-call 'edebug-form-spec '(form)) -(put 'reader::encapsulate-recursive-call 'lisp-indent-function 0) - -(defun reader::read-from-buffer (&optional stream reader::recursive-p) - (or (bufferp stream) - (reader::error "Sorry, can only read on buffers")) - (if (not reader::recursive-p) - ;; set up environment for shared structure reading - (let (reader::shared-structure-references - reader::shared-structure-labels - tmp-sexp) - ;; the reader returns an unshared sexpr, possibly containing - ;; symbolic references - (setq tmp-sexp (reader::read-from-buffer stream 't)) - (if ;; sexpr actually contained shared structures - reader::shared-structure-references - (reader::restore-shared-structure tmp-sexp) - ;; it did not, so don't bother about restoring - tmp-sexp)) - - (loop for char = (following-char) - for entry = (reader::get-readtable-entry char *readtable*) - if (eobp) do (reader::error "End of file during reading") - do - (cond - - ((eq entry 'illegal) - (reader::error "`%c' has illegal character syntax" char)) - - ;; skipping whitespace characters must be done inside this - ;; loop as character macro subroutines may return without - ;; leaving the loop using (throw 'reader-ignore ...) - ((eq entry 'whitespace) - (forward-char 1) - ;; skip all whitespace - (while (eq 'whitespace - (reader::get-readtable-entry - (following-char) *readtable*)) - (forward-char 1))) - - ;; for every token starting with a constituent character - ;; call the built-in reader (symbols, numbers, strings, - ;; characters with ? syntax) - ((eq entry 'constituent) - (reader::encapsulate-recursive-call - (reader::read-constituent stream))) - - ((vectorp entry) - ;; Dispatch macro character. The dispatch macro character - ;; function is contained in the vector `entry', at the - ;; place indicated by , the first non-digit - ;; character following the : - ;; * - (reader::encapsulate-recursive-call - (loop initially do (forward-char 1) - for sub-char = (prog1 (following-char) - (forward-char 1)) - while (memq sub-char - '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)) - collect sub-char into digit-args - finally - (return - (funcall - ;; no test is done here whether a non-nil - ;; contents is a correct dispatch character - ;; function to apply. - (or (aref entry sub-char) - (reader::error - "Undefined subsequent dispatch character `%c'" - sub-char)) - stream - sub-char - (string-to-int - (apply 'concat - (mapcar - 'char-to-string digit-args)))))))) - - (t - ;; must be a macro character. In this case, `entry' is - ;; the function to be called - (reader::encapsulate-recursive-call - (progn - (forward-char 1) - (funcall entry stream char)))))))) - - -;; Constituent reader fix for Emacs 18 -(if (string-match "^19" emacs-version) - (defun reader::read-constituent (stream) - (reader::read-sexp (point) - (reader::original-read stream))) - - (defun reader::read-constituent (stream) - (reader::read-sexp (point) - (prog1 (reader::original-read stream) - ;; For Emacs 18, backing up is necessary because the `read' function - ;; reads one character too far after reading a symbol or number. - ;; This doesnt apply to reading chars (e.g. ?n). - ;; This still loses for escaped chars. - (if (not (eq (reader::get-readtable-entry - (preceding-char) *readtable*) 'constituent)) - (forward-char -1)))))) - - -;; Make the default current CL readtable - -(defconst *readtable* - (loop with raw-readtable = - (make-vector (1+ reader::readtable-size) 'illegal) - initially do (setf (aref raw-readtable reader::readtable-size) - 'readtable) - for entry in - '((constituent ?! ?@ ?$ ?% ?& ?* ?_ ?- ?+ ?= ?/ ?\\ ?0 ?1 ?2 - ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?: ?~ ?> ?< ?a ?b - ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p - ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z ?A ?B ?C ?D - ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R - ?S ?T ?U ?V ?W ?X ?Y ?Z) - (whitespace ? ?\t ?\n ?\r ?\f) - - ;; The following CL character classes are only useful for - ;; token parsing. We don't need them, as token parsing is - ;; left to the built-in reader. - ;; (single-escape ?\\) - ;; (multiple-escape ?|) - ) - do - (loop for char in (rest entry) - do (setf (reader::get-readtable-entry char raw-readtable) - (first entry))) - finally return raw-readtable) - "The current readtable.") - - -;; Variables used non-locally in the standard readmacros -(defvar reader::context) -(defvar reader::stack) -(defvar reader::recursive-p) - - -;;;; Read macro character definitions - -;;; Hint for modifying, testing and debugging new read macros: All the -;;; read macros and dispatch character macros below are defined in -;;; the `*readtable*'. Modifications or -;;; instrumenting with edebug are effective immediately without having to -;;; copy the internal readtable to the standard *readtable*. However, -;;; if you wish to modify reader::internal-standard-readtable, then -;;; you must recopy *readtable*. - -;; Chars and strings - -;; This is defined to distinguish chars from constituents -;; since chars are read by the standard reader without reading too far. -(set-macro-character ?\? - (function - (lambda (stream char) - (forward-char -1) - (reader::read-sexp (point) - (reader::original-read stream))))) - -;; ?\M-\C-a - -;; This is defined to distinguish strings from constituents -;; since backing up after reading a string is simpler. -(set-macro-character ?\" - (function - (lambda (stream char) - (forward-char -1) - (reader::read-sexp (point) - (prog1 (reader::original-read stream) - ;; This is not needed with Emacs 19, but it is OK. See above. - (if (/= (preceding-char) ?\") - (forward-char -1))))))) - -;; Lists and dotted pairs -(set-macro-character ?\( - (function - (lambda (stream char) - (reader::read-sexp (1- (point)) - (catch 'read-list - (let ((reader::context 'list) reader::stack ) - ;; read list elements up to a `.' - (catch 'dotted-pair - (while t - (setq reader::stack (cons (reader::read-from-buffer stream 't) - reader::stack)))) - ;; In dotted pair. Read one more element - (setq reader::stack (cons (reader::read-from-buffer stream 't) - reader::stack) - ;; signal it to the closing paren - reader::context 'dotted-pair) - ;; Next char *must* be the closing paren that throws read-list - (reader::read-from-buffer stream 't) - ;; otherwise an error is signalled - (reader::error "Illegal dotted pair read syntax"))))))) - -(set-macro-character ?\) - (function - (lambda (stream char) - (cond ((eq reader::context 'list) - (throw 'read-list (nreverse reader::stack))) - ((eq reader::context 'dotted-pair) - (throw 'read-list (nconc (nreverse (cdr reader::stack)) - (car reader::stack)))) - (t - (reader::error "`)' doesn't end a list")))))) - -(set-macro-character ?\. - (function - (lambda (stream char) - (and (eq reader::context 'dotted-pair) - (reader::error "No more than one `.' allowed in list")) - (throw 'dotted-pair nil)))) - -;; '(#\a . #\b) -;; '(a . (b . c)) - -;; Vectors: [a b] -(set-macro-character ?\[ - (function - (lambda (stream char) - (reader::read-sexp (1- (point)) - (let ((reader::context 'vector)) - (catch 'read-vector - (let ((reader::context 'vector) - reader::stack) - (while t (push (reader::read-from-buffer stream 't) - reader::stack))))))))) - -(set-macro-character ?\] - (function - (lambda (stream char) - (if (eq reader::context 'vector) - (throw 'read-vector (apply 'vector (nreverse reader::stack))) - (reader::error "`]' doesn't end a vector"))))) - -;; Quote and backquote/comma macro -(set-macro-character ?\' - (function - (lambda (stream char) - (reader::read-sexp (1- (point)) - (list (reader::read-sexp (point) 'quote) - (reader::read-from-buffer stream 't)))))) - -(set-macro-character ?\` - (function - (lambda (stream char) - (if (= (following-char) ?\ ) - ;; old backquote syntax. This is ambigous, because - ;; (`(sexp)) is a valid form in both syntaxes, but - ;; unfortunately not the same. - ;; old syntax: read -> (` (sexp)) - ;; new syntax: read -> ((` (sexp))) - (reader::read-sexp (1- (point)) '\`) - (reader::read-sexp (1- (point)) - (list (reader::read-sexp (point) '\`) - (reader::read-from-buffer stream 't))))))) - -(set-macro-character ?\, - (function - (lambda (stream char) - (cond ((eq (following-char) ?\ ) - ;; old syntax - (reader::read-sexp (point) '\,)) - ((eq (following-char) ?\@) - (forward-char 1) - (cond ((eq (following-char) ?\ ) - (reader::read-sexp (point) '\,\@)) - (t - (reader::read-sexp (- (point) 2) - (list - (reader::read-sexp (point) '\,\@) - (reader::read-from-buffer stream 't)))))) - (t - (reader::read-sexp (1- (point)) - (list - (reader::read-sexp (1- (point)) '\,) - (reader::read-from-buffer stream 't)))))))) - -;; 'a -;; '(a b c) -;; (let ((a 10) (b '(20 30))) `(,a ,@b c)) -;; the old syntax is also supported: -;; (let ((a 10) (b '(20 30))) (` ((, a) (,@ b) c))) - -;; Single line character comment: ; -(set-macro-character ?\; - (function - (lambda (stream char) - (skip-chars-forward "^\n\r") - (throw 'reader-ignore nil)))) - - - -;; Dispatch character character # -(make-dispatch-macro-character ?\#) - -(defsubst reader::check-0-infix (n) - (or (= n 0) - (reader::error "Numeric infix argument not allowed: %d" n))) - - -(defalias 'search-forward-regexp 're-search-forward) - -;; nested multi-line comments #| ... |# -(set-dispatch-macro-character ?\# ?\| - (function - (lambda (stream char n) - (reader::check-0-infix n) - (let ((counter 0)) - (while (search-forward-regexp "#|\\||#" nil t) - (if (string-equal - (buffer-substring - (match-beginning 0) (match-end 0)) - "|#") - (cond ((> counter 0) - (decf counter)) - ((= counter 0) - ;; stop here - (goto-char (match-end 0)) - (throw 'reader-ignore nil)) - ('t - (reader::error "Unmatching closing multicomment"))) - (incf counter))) - (reader::error "Unmatching opening multicomment"))))) - -;; From cl-packages.el -(defconst reader::symbol-characters "[A-Za-z0-9-_!@$%^&*+=|~{}<>/]") -(defconst reader::symbol-regexp2 - (format "\\(%s+\\)" reader::symbol-characters)) - -(set-dispatch-macro-character ?\# ?\: - (function - (lambda (stream char n) - (reader::check-0-infix n) - (or (looking-at reader::symbol-regexp2) - (reader::error "Invalid symbol read syntax")) - (goto-char (match-end 0)) - (make-symbol - (buffer-substring (match-beginning 0) (match-end 0)))))) - -;; Function quoting: #' -(set-dispatch-macro-character ?\# ?\' - (function - (lambda (stream char n) - (reader::check-0-infix n) - ;; Probably should test if cl is required by current buffer. - ;; Currently, cl will always be a feature because cl-read requires it. - (reader::read-sexp (- (point) 2) - (list - (reader::read-sexp (point) (if (featurep 'cl) 'function* 'function)) - (reader::read-from-buffer stream 't)))))) - -;; Character syntax: #\ -;; Not yet implemented: #\Control-a #\M-C-a etc. -;; This definition is not used - the next one is more general. -'(set-dispatch-macro-character ?# ?\\ - (function - (lambda (stream char n) - (reader::check-0-infix n) - (let ((next (following-char)) - name) - (if (not (and (<= ?a next) (<= next ?z))) - (progn (forward-char 1) next) - (setq next (reader::read-from-buffer stream t)) - (cond ((symbolp next) (setq name (symbol-name next))) - ((integerp next) (setq name (int-to-string next)))) - (if (= 1 (length name)) - (string-to-char name) - (case next - (linefeed ?\n) - (newline ?\r) - (space ?\ ) - (rubout ?\b) - (page ?\f) - (tab ?\t) - (return ?\C-m) - (t - (reader::error "Unknown character specification `%s'" - next)))))))) - ) - -(defvar reader::special-character-name-table - '(("linefeed" . ?\n) - ("newline" . ?\r) - ("space" . ?\ ) - ("rubout" . ?\b) - ("page" . ?\f) - ("tab" . ?\t) - ("return" . ?\C-m))) - -(set-dispatch-macro-character ?# ?\\ - (function - (lambda (stream char n) - (reader::check-0-infix n) - (forward-char -1) - ;; We should read in a special package to avoid creating symbols. - (let ((symbol (reader::read-from-buffer stream t)) - (case-fold-search t) - name modifier character char-base) - (setq name (symbol-name symbol)) - (if (string-match "^\\(meta-\\|m-\\|control-\\|c-\\)+" name) - (setq modifier (substring name - (match-beginning 1) - (match-end 1)) - character (substring name (match-end 1))) - (setq character name)) - (setq char-base - (cond ((= (length character) 1) - (string-to-char character)) - ('t - (cdr (assoc character - reader::special-character-name-table))))) - (or char-base - (reader::error - "Unknown character specification `%s'" character)) - - (and modifier - (progn - (and (string-match "control-\\|c-" modifier) - (decf char-base 32)) - (and (string-match "meta-\\|m-" modifier) - (incf char-base 128)))) - char-base)))) - -;; '(#\meta-space #\tab #\# #\> #\< #\a #\A #\return #\space) -;; (eq #\m-tab ?\M-\t) -;; (eq #\c-m-x #\m-c-x) -;; (eq #\Meta-Control-return #\M-C-return) -;; (eq #\m-m-c-c-x #\m-c-x) -;; #\C-space #\C-@ ?\C-@ - - - -;; Read and load time evaluation: #. -;; Not yet implemented: #, -(set-dispatch-macro-character ?\# ?\. - (function - (lambda (reader::stream reader::char reader::n) - (reader::check-0-infix reader::n) - ;; This eval will see all internal vars of reader, - ;; e.g. stream, reader::recursive-p. Anything that might be bound. - ;; We must use `read' here rather than read-from-buffer with 'recursive-p - ;; because the expression must not have unresolved #n#s in it anyway. - ;; Otherwise the top-level expression must be completely read before - ;; any embedded evaluation(s) occur(s). CLtL2 does not specify this. - ;; Also, call `read' so that it may be customized, by e.g. Edebug - (eval (read reader::stream))))) -;; '(#.(current-buffer) #.(get-buffer "*scratch*")) - -;; Path names (kind of): #p, #P, -(set-dispatch-macro-character ?\# ?\P - (function - (lambda (stream char n) - (reader::check-0-infix n) - (let ((string (reader::read-from-buffer stream 't))) - (or (stringp string) - (reader::error "Pathname must be a string: %s" string)) - (expand-file-name string))))) - -(set-dispatch-macro-character ?\# ?\p - (get-dispatch-macro-character ?\# ?\P)) - -;; #P"~/.emacs" -;; #p"~root/home" - -;; Feature reading: #+, #- -;; Not yet implemented: #+, #- - - -(defsubst reader::read-feature (stream char n flag) - (reader::check-0-infix n) - (let (;; Use the original reader to only read the feature. - ;; This is not exactly correct without *read-suppress*. - ;; Also Emacs 18 read goes one too far, - ;; so we assume there is a space after the feature. - (feature (reader::original-read stream)) - (object (reader::read-from-buffer stream 't))) - (if (eq (featurep feature) flag) - object - ;; Ignore it. - (throw 'reader-ignore nil)))) - -(set-dispatch-macro-character ?\# ?\+ - (function - (lambda (stream char n) - (reader::read-feature stream char n t)))) - -(set-dispatch-macro-character ?\# ?\- - (function - (lambda (stream char n) - (reader::read-feature stream char n nil)))) - -;; (#+cl loop #+cl do #-cl while #-cl t (body)) - - - - -;; Shared structure reading: #=, ## - -;; Reading of sexpression with shared and circular structure read -;; syntax is done in two steps: -;; -;; 1. Create an sexpr with unshared structures, just as the ordinary -;; read macros do, with two exceptions: -;; - each label (#=) creates, as a side effect, a symbolic -;; reference for the sexpr that follows it -;; - each reference (##) is replaced by the corresponding -;; symbolic reference. -;; -;; 2. This non-cyclic and unshared lisp structure is given to the -;; function `reader::restore-shared-structure' (see -;; `reader::read-from-buffer'), which simply replaces -;; destructively all symbolic references by the lisp structures the -;; references point at. -;; -;; A symbolic reference is an uninterned symbol whose name is obtained -;; from the label/reference number using the function `int-to-string': -;; -;; There are two non-locally used variables (bound in -;; `reader::read-from-buffer') which control shared structure reading: -;; `reader::shared-structure-labels': -;; A list of integers that correspond to the label numbers in -;; the string currently read. This is used to avoid multiple -;; definitions of the same label. -;; `reader::shared-structure-references': -;; The list of symbolic references that will be used as temporary -;; placeholders for the shared objects introduced by a reference -;; with the same number identification. - -(set-dispatch-macro-character ?\# ?\= - (function - (lambda (stream char n) - (and (= n 0) (reader::error "0 not allowed as label")) - ;; check for multiple definition of the same label - (if (memq n reader::shared-structure-labels) - (reader::error "Label defined twice") - (push n reader::shared-structure-labels)) - ;; create an uninterned symbol as symbolic reference for the label - (let* ((string (int-to-string n)) - (ref (or (find string reader::shared-structure-references - :test 'string=) - (first - (push (make-symbol string) - reader::shared-structure-references))))) - ;; the link between the symbolic reference and the lisp - ;; structure it points at is done using the symbol value cell - ;; of the reference symbol. - (setf (symbol-value ref) - ;; this is also the return value - (reader::read-from-buffer stream 't)))))) - - -(set-dispatch-macro-character ?\# ?\# - (function - (lambda (stream char n) - (and (= n 0) (reader::error "0 not allowed as label")) - ;; use the non-local variable `reader::recursive-p' (from the reader - ;; main loop) to detect labels at the top level of an sexpr. - (if (not reader::recursive-p) - (reader::error "References at top level not allowed")) - (let* ((string (int-to-string n)) - (ref (or (find string reader::shared-structure-references - :test 'string=) - (first - (push (make-symbol string) - reader::shared-structure-references))))) - ;; the value of reading a #n# form is a reference symbol - ;; whose symbol value is or will be the shared structure. - ;; `reader::restore-shared-structure' then replaces the symbol by - ;; its value. - ref)))) - -(defun reader::restore-shared-structure (obj) - ;; traverses recursively OBJ and replaces all symbolic references by - ;; the objects they point at. Remember that a symbolic reference is - ;; an uninterned symbol whose value is the object it points at. - (cond - ((consp obj) - (loop for rest on obj - as lastcdr = rest - do - (if;; substructure is a symbolic reference - (memq (car rest) reader::shared-structure-references) - ;; replace it by its symbol value, i.e. the associated object - (setf (car rest) (symbol-value (car rest))) - (reader::restore-shared-structure (car rest))) - finally - (if (memq (cdr lastcdr) reader::shared-structure-references) - (setf (cdr lastcdr) (symbol-value (cdr lastcdr))) - (reader::restore-shared-structure (cdr lastcdr))))) - ((vectorp obj) - (loop for i below (length obj) - do - (if;; substructure is a symbolic reference - (memq (aref obj i) reader::shared-structure-references) - ;; replace it by its symbol value, i.e. the associated object - (setf (aref obj i) (symbol-value (aref obj i))) - (reader::restore-shared-structure (aref obj i)))))) - obj) - - -;; #1=(a b #3=[#2=c]) -;; (#1=[#\return #\a] #1# #1#) -;; (#1=[a b c] #1# #1#) -;; #1=(a b . #1#) - -;; Creation and initialization of an internal standard readtable. -;; Do this after all the macros and dispatch chars above have been defined. - -(defconst reader::internal-standard-readtable (copy-readtable) - "The original (CL-like) standard readtable. If you ever modify this -readtable, you won't be able to recover a standard readtable using -\(copy-readtable nil\)") - - -;; Replace built-in functions that call the built-in reader -;; -;; The following functions are replaced here: -;; -;; read by reader::read -;; read-from-string by reader::read-from-string -;; -;; eval-expression by reader::eval-expression -;; Why replace eval-expression? Not needed for Lucid Emacs since the -;; reader for arguments is also written in Lisp, and so may be overridden. -;; -;; eval-current-buffer by reader::eval-current-buffer -;; eval-buffer by reader::eval-buffer -;; original-eval-region by reader::original-eval-region - - -;; Temporary read buffer used for reading from strings -(defconst reader::tmp-buffer - (get-buffer-create " *CL Read*")) - -;; Save a pointer to the original read function -(or (fboundp 'reader::original-read) - (fset 'reader::original-read (symbol-function 'read))) - -(defun reader::read (&optional stream reader::recursive-p) - "Read one Lisp expression as text from STREAM, return as Lisp object. -If STREAM is nil, use the value of `standard-input' \(which see\). -STREAM or the value of `standard-input' may be: - a buffer \(read from point and advance it\) - a marker \(read from where it points and advance it\) - a string \(takes text from string, starting at the beginning\) - t \(read text line using minibuffer and use it\). - -This is the cl-read replacement of the standard elisp function -`read'. The only incompatibility is that functions as stream arguments -are not supported." - (if (not cl-read-active) - (reader::original-read stream) - (if (null stream) ; read from standard-input - (setq stream standard-input)) - - (if (eq stream 't) ; read from minibuffer - (setq stream (read-from-minibuffer "Common Lisp Expression: "))) - - (cond - - ((bufferp stream) ; read from buffer - (reader::read-from-buffer stream reader::recursive-p)) - - ((markerp stream) ; read from marker - (save-excursion - (set-buffer (marker-buffer stream)) - (goto-char (marker-position stream)) - (reader::read-from-buffer (current-buffer) reader::recursive-p))) - - ((stringp stream) ; read from string - (save-excursion - (set-buffer reader::tmp-buffer) - (auto-save-mode -1) - (erase-buffer) - (insert stream) - (goto-char (point-min)) - (reader::read-from-buffer reader::tmp-buffer reader::recursive-p))) - (t - (reader::error "Not a valid stream: %s" stream))))) - -;; read-from-string -;; save a pointer to the original `read-from-string' function -(or (fboundp 'reader::original-read-from-string) - (fset 'reader::original-read-from-string - (symbol-function 'read-from-string))) - -(defun reader::read-from-string (string &optional start end) - "Read one Lisp expression which is represented as text by STRING. -Returns a cons: (OBJECT-READ . FINAL-STRING-INDEX). -START and END optionally delimit a substring of STRING from which to read; -they default to 0 and (length STRING) respectively. - -This is the cl-read replacement of the standard elisp function -`read-from-string'. It uses the reader macros in *readtable* if -`cl-read-active' is non-nil in the current buffer." - - ;; Does it really make sense to have read-from-string depend on - ;; what the current buffer happens to be? Yes, so code that - ;; has nothing to do with cl-read uses original reader. - (if (not cl-read-active) - (reader::original-read-from-string string start end) - (or start (setq start 0)) - (or end (setq end (length string))) - (save-excursion - (set-buffer reader::tmp-buffer) - (auto-save-mode -1) - (erase-buffer) - (insert (substring string 0 end)) - (goto-char (1+ start)) - (cons - (reader::read-from-buffer reader::tmp-buffer nil) - (1- (point)))))) - -;; (read-from-string "abc (car 'a) bc" 4) -;; (reader::read-from-string "abc (car 'a) bc" 4) -;; (read-from-string "abc (car 'a) bc" 2 11) -;; (reader::read-from-string "abc (car 'a) bc" 2 11) -;; (reader::read-from-string "`(car ,first ,@rest)") -;; (read-from-string ";`(car ,first ,@rest)") -;; (reader::read-from-string ";`(car ,first ,@rest)") - -;; We should replace eval-expression, too, so that it reads (and -;; evals) in the current buffer. Alternatively, this could be fixed -;; in C. In Lemacs 19.6 and later, this function is already written -;; in lisp, and based on more primitive read functions we already -;; replaced. The reading happens during the interactive parameter -;; retrieval, which is written in lisp, too. So this replacement of -;; eval-expression is only required for (FSF) Emacs 18 (and 19?). - -(or (fboundp 'reader::original-eval-expression) - (fset 'reader::original-eval-expression - (symbol-function 'eval-expression))) - -(defun reader::eval-expression (reader::expression) - "Evaluate EXPRESSION and print value in minibuffer. -Value is also consed on to front of variable `values'." - (interactive - (list - (car (read-from-string - (read-from-minibuffer - "Eval: " nil - ;;read-expression-map ;; not for emacs 18 - nil ;; use default map - nil ;; don't do read with minibuffer current. - ;; 'edebug-expression-history ;; not for emacs 18 - ))))) - (setq values (cons (eval reader::expression) values)) - (prin1 (car values) t)) - -(require 'eval-reg "eval-reg") -; (require 'advice) - - -;; installing/uninstalling the cl reader -;; These two should always be used in pairs, or just install once and -;; never uninstall. -(defun cl-reader-install () - (interactive) - (fset 'read 'reader::read) - (fset 'read-from-string 'reader::read-from-string) - (fset 'eval-expression 'reader::eval-expression) - (elisp-eval-region-install)) - -(defun cl-reader-uninstall () - (interactive) - (fset 'read - (symbol-function 'reader::original-read)) - (fset 'read-from-string - (symbol-function 'reader::original-read-from-string)) - (fset 'eval-expression - (symbol-function 'reader::original-eval-expression)) - (elisp-eval-region-uninstall)) - -;; Globally installing the cl-read replacement functions is safe, even -;; for buffers without cl read syntax. The buffer local variable -;; `cl-read-active' controls whether the replacement funtions of this -;; package or the original ones are actually called. -(cl-reader-install) -(cl-reader-uninstall) - -(add-hook 'emacs-lisp-mode-hook 'cl-reader-autoinstall-function) - -'(defvar read-syntax) - -'(defun cl-reader-autoinstall-function () - "Activates the Common Lisp style reader for emacs-lisp-mode buffers, -if the property line has a local variable setting like this: -\;\; -*- Read-Syntax: Common-Lisp -*-" - ;; this is a hack to avoid recursion in the case that the prop line - ;; containes "Mode: emacs-lisp" entry - (or (boundp 'local-variable-hack-done) - (let (local-variable-hack-done - (case-fold-search t)) - ;; Usually `hack-local-variables-prop-line' is called only after - ;; installation of the major mode. But we need to know about the - ;; local variables before that, so we call the local variable hack - ;; explicitly here: - (hack-local-variables-prop-line 't) - ;; But hack-local-variables-prop-line not defined in emacs 18. - (cond - ((and (boundp 'read-syntax) - read-syntax - (string-match "^common-lisp$" (symbol-name read-syntax))) - (require 'cl-read) - (make-local-variable 'cl-read-active) - (setq cl-read-active 't)))))) - -;; Emacs 18 doesnt have hack-local-variables-prop-line. So use this instead. -(defun cl-reader-autoinstall-function () - (save-excursion - (goto-char (point-min)) - (let ((case-fold-search t)) - (cond ((re-search-forward - "read-syntax: *common-lisp" - (save-excursion - (end-of-line) - (point)) - t) - (require 'cl-read) - (make-local-variable 'cl-read-active) - (setq cl-read-active t)))))) - - -(run-hooks 'cl-read-load-hooks) - -;; cl-read.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/cl-specs.el --- a/lisp/edebug/cl-specs.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,477 +0,0 @@ -;; cl-specs.el - Edebug specs for cl.el - -;; Copyright (C) 1993 Free Software Foundation, Inc. -;; Author: Daniel LaLiberte -;; Keywords: lisp, tools, maint - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; LCD Archive Entry: -;; cl-specs.el|Daniel LaLiberte|liberte@cs.uiuc.edu -;; |Edebug specs for cl.el -;; |$Date: 1996/12/18 22:51:45 $|$Revision: 1.1.1.2 $|~/modes/cl-specs.el| - -;; These specs are to be used with edebug.el version 3.3 or later and -;; cl.el version 2.03 or later, by Dave Gillespie . - -;; This file need not be byte-compiled, but it shouldn't hurt. - -;;; Code: - -(provide 'cl-specs) -;; Do the above provide before the following require. -;; Otherwise if you load this before edebug if cl is already loaded -;; an infinite loading loop would occur. -(require 'edebug) - -;; Blocks - -(def-edebug-spec block (symbolp body)) -(def-edebug-spec return (&optional form)) -(def-edebug-spec return-from (symbolp &optional form)) - -;; Loops - -(def-edebug-spec when t) -(def-edebug-spec unless t) -(def-edebug-spec case (form &rest (sexp body))) -(def-edebug-spec ecase case) -(def-edebug-spec do - ((&rest &or symbolp (symbolp &optional form form)) - (form body) - cl-declarations body)) -(def-edebug-spec do* do) -(def-edebug-spec dolist - ((symbolp form &optional form) cl-declarations body)) -(def-edebug-spec dotimes dolist) -(def-edebug-spec do-symbols - ((symbolp &optional form form) cl-declarations body)) -(def-edebug-spec do-all-symbols - ((symbolp &optional form) cl-declarations body)) - -;; Multiple values - -(def-edebug-spec multiple-value-list (form)) -(def-edebug-spec multiple-value-call (function-form body)) -(def-edebug-spec multiple-value-bind - ((&rest symbolp) form cl-declarations body)) -(def-edebug-spec multiple-value-setq ((&rest symbolp) form)) -(def-edebug-spec multiple-value-prog1 (form body)) - -;; Bindings - -(def-edebug-spec lexical-let let) -(def-edebug-spec lexical-let* let) - -(def-edebug-spec psetq setq) -(def-edebug-spec progv (form form body)) - -(def-edebug-spec flet ((&rest (defun*)) cl-declarations body)) -(def-edebug-spec labels flet) - -(def-edebug-spec macrolet - ((&rest (&define name (&rest arg) cl-declarations-or-string def-body)) - cl-declarations body)) - -(def-edebug-spec symbol-macrolet - ((&rest (symbol sexp)) cl-declarations body)) - -(def-edebug-spec destructuring-bind - (&define cl-macro-list form cl-declarations def-body)) - -;; Setf - -(def-edebug-spec setf (&rest [place form])) ;; sexp is not specific enough -(def-edebug-spec psetf setf) - -(def-edebug-spec letf ;; *not* available in Common Lisp - ((&rest (gate place &optional form)) - body)) -(def-edebug-spec letf* letf) - - -(def-edebug-spec defsetf - (&define name - [&or [symbolp &optional stringp] - [cl-lambda-list (symbolp)]] - cl-declarations-or-string def-body)) - -(def-edebug-spec define-setf-method - (&define name cl-lambda-list cl-declarations-or-string def-body)) - -(def-edebug-spec define-modify-macro - (&define name cl-lambda-list ;; should exclude &key - symbolp &optional stringp)) - -(def-edebug-spec callf (function* place &rest form)) -(def-edebug-spec callf2 (function* form place &rest form)) - -;; Other operations on places - -(def-edebug-spec remf (place form)) - -(def-edebug-spec incf (place &optional form)) -(def-edebug-spec decf incf) -(def-edebug-spec push (form place)) -(def-edebug-spec pushnew - (form place &rest - &or [[&or ":test" ":test-not" ":key"] function-form] - [keywordp form])) -(def-edebug-spec pop (place)) - -(def-edebug-spec shiftf (&rest place)) ;; really [&rest place] form -(def-edebug-spec rotatef (&rest place)) - - -;; Functions with function args. These are only useful if the -;; function arg is quoted with ' instead of function. - -(def-edebug-spec some (function-form form &rest form)) -(def-edebug-spec every some) -(def-edebug-spec notany some) -(def-edebug-spec notevery some) - -;; Mapping - -(def-edebug-spec map (form function-form form &rest form)) -(def-edebug-spec maplist (function-form form &rest form)) -(def-edebug-spec mapc maplist) -(def-edebug-spec mapl maplist) -(def-edebug-spec mapcan maplist) -(def-edebug-spec mapcon maplist) - -;; Sequences - -(def-edebug-spec reduce (function-form form &rest form)) - -;; Types and assertions - -(def-edebug-spec cl-type-spec (sexp)) ;; not worth the trouble to specify, yet. - -(def-edebug-spec deftype defmacro*) -(def-edebug-spec check-type (place cl-type-spec &optional stringp)) -;; (def-edebug-spec assert (form &optional form stringp &rest form)) -(def-edebug-spec assert (form &rest form)) -(def-edebug-spec typecase (form &rest ([&or cl-type-spec "otherwise"] body))) -(def-edebug-spec etypecase typecase) - -(def-edebug-spec ignore-errors t) - -;; Time of Evaluation - -(def-edebug-spec eval-when - ((&rest &or "compile" "load" "eval") body)) -(def-edebug-spec load-time-value (form &optional &or "t" "nil")) - -;; Declarations - -(def-edebug-spec cl-decl-spec - ((symbolp &rest sexp))) - -(def-edebug-spec cl-declarations - (&rest ("declare" &rest cl-decl-spec))) - -(def-edebug-spec cl-declarations-or-string - (&or stringp cl-declarations)) - -(def-edebug-spec declaim (&rest cl-decl-spec)) -(def-edebug-spec declare (&rest cl-decl-spec)) ;; probably not needed. -(def-edebug-spec locally (cl-declarations &rest form)) -(def-edebug-spec the (cl-type-spec form)) - -;;====================================================== -;; Lambda things - -(def-edebug-spec cl-lambda-list - (([&rest arg] - [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]] - [&optional ["&rest" arg]] - [&optional ["&key" [cl-&key-arg &rest cl-&key-arg] - &optional "&allow-other-keywords"]] - [&optional ["&aux" &rest - &or (symbolp &optional def-form) symbolp]] - ))) - -(def-edebug-spec cl-&optional-arg - (&or (arg &optional def-form arg) arg)) - -(def-edebug-spec cl-&key-arg - (&or ([&or (symbolp arg) arg] &optional def-form arg) arg)) - -;; The lambda list for macros is different from that of normal lambdas. -;; Note that &environment is only allowed as first or last items in the -;; top level list. - -(def-edebug-spec cl-macro-list - (([&optional "&environment" arg] - [&rest cl-macro-arg] - [&optional ["&optional" &rest - &or (cl-macro-arg &optional def-form cl-macro-arg) arg]] - [&optional [[&or "&rest" "&body"] cl-macro-arg]] - [&optional ["&key" [&rest - [&or ([&or (symbolp cl-macro-arg) arg] - &optional def-form cl-macro-arg) - arg]] - &optional "&allow-other-keywords"]] - [&optional ["&aux" &rest - &or (symbolp &optional def-form) symbolp]] - [&optional "&environment" arg] - ))) - -(def-edebug-spec cl-macro-arg - (&or arg cl-macro-list1)) - -(def-edebug-spec cl-macro-list1 - (([&optional "&whole" arg] ;; only allowed at lower levels - [&rest cl-macro-arg] - [&optional ["&optional" &rest - &or (cl-macro-arg &optional def-form cl-macro-arg) arg]] - [&optional [[&or "&rest" "&body"] cl-macro-arg]] - [&optional ["&key" [&rest - [&or ([&or (symbolp cl-macro-arg) arg] - &optional def-form cl-macro-arg) - arg]] - &optional "&allow-other-keywords"]] - [&optional ["&aux" &rest - &or (symbolp &optional def-form) symbolp]] - . [&or arg nil]))) - - -(def-edebug-spec defun* - ;; Same as defun but use cl-lambda-list. - (&define [&or name - ("setf" :name setf name)] - cl-lambda-list - cl-declarations-or-string - [&optional ("interactive" interactive)] - def-body)) -(def-edebug-spec defsubst* defun*) - -(def-edebug-spec defmacro* - (&define name cl-macro-list cl-declarations-or-string def-body)) -(def-edebug-spec define-compiler-macro defmacro*) - - -(def-edebug-spec function* - (&or symbolp cl-lambda-expr)) - -(def-edebug-spec cl-lambda-expr - (&define ("lambda" cl-lambda-list - ;;cl-declarations-or-string - ;;[&optional ("interactive" interactive)] - def-body))) - -;; Redefine function-form to also match function* -(def-edebug-spec function-form - ;; form at the end could also handle "function", - ;; but recognize it specially to avoid wrapping function forms. - (&or ([&or "quote" "function"] &or symbolp lambda-expr) - ("function*" cl-lambda-expr) - form)) - -;;====================================================== -;; Structures -;; (def-edebug-spec defstruct (&rest sexp)) would be sufficient, but... - -;; defstruct may contain forms that are evaluated when a structure is created. -(def-edebug-spec defstruct - (&define ; makes top-level form not be wrapped - [&or symbolp - (gate - symbolp &rest - (&or [":conc-name" &or stringp "nil"] - [":constructor" symbolp &optional cl-lambda-list] - [":copier" symbolp] - [":predicate" symbolp] - [":include" symbolp &rest sexp];; not finished - ;; The following are not supported. - ;; [":print-function" ...] - ;; [":type" ...] - ;; [":initial-offset" ...] - ))] - [&optional stringp] - ;; All the above is for the following def-form. - &rest &or symbolp (symbolp def-form &optional ":read-only" sexp))) - -;;====================================================== -;; Loop - -;; The loop macro is very complex, and a full spec is found below. -;; The following spec only minimally specifies that -;; parenthesized forms are executable, but single variables used as -;; expressions will be missed. You may want to use this if the full -;; spec causes problems for you. - -(def-edebug-spec loop - (&rest &or symbolp form)) - -;; Below is a complete spec for loop, in several parts that correspond -;; to the syntax given in CLtL2. The specs do more than specify where -;; the forms are; it also specifies, as much as Edebug allows, all the -;; syntactically legal loop clauses. The disadvantage of this -;; completeness is rigidity, but the "for ... being" clause allows -;; arbitrary extensions of the form: [symbolp &rest &or symbolp form]. - -(def-edebug-spec loop - ([&optional ["named" symbolp]] - [&rest - &or - ["repeat" form] - loop-for-as - loop-with - loop-initial-final] - [&rest loop-clause] - )) - -(def-edebug-spec loop-with - ("with" loop-var - loop-type-spec - [&optional ["=" form]] - &rest ["and" loop-var - loop-type-spec - [&optional ["=" form]]])) - -(def-edebug-spec loop-for-as - ([&or "for" "as"] loop-for-as-subclause - &rest ["and" loop-for-as-subclause])) - -(def-edebug-spec loop-for-as-subclause - (loop-var - loop-type-spec - &or - [[&or "in" "on" "in-ref" "across-ref"] - form &optional ["by" function-form]] - - ["=" form &optional ["then" form]] - ["across" form] - ["being" - [&or "the" "each"] - &or - [[&or "element" "elements"] - [&or "of" "in" "of-ref"] form - &optional "using" ["index" symbolp]];; is this right? - [[&or "hash-key" "hash-keys" - "hash-value" "hash-values"] - [&or "of" "in"] - hash-table-p &optional ["using" ([&or "hash-value" "hash-values" - "hash-key" "hash-keys"] sexp)]] - - [[&or "symbol" "present-symbol" "external-symbol" - "symbols" "present-symbols" "external-symbols"] - [&or "in" "of"] package-p] - - ;; Extensions for Emacs Lisp, including Lucid Emacs. - [[&or "frame" "frames" - "screen" "screens" - "buffer" "buffers"]] - - [[&or "window" "windows"] - [&or "of" "in"] form] - - [[&or "overlay" "overlays" - "extent" "extents"] - [&or "of" "in"] form - &optional [[&or "from" "to"] form]] - - [[&or "interval" "intervals"] - [&or "in" "of"] form - &optional [[&or "from" "to"] form] - ["property" form]] - - [[&or "key-code" "key-codes" - "key-seq" "key-seqs" - "key-binding" "key-bindings"] - [&or "in" "of"] form - &optional ["using" ([&or "key-code" "key-codes" - "key-seq" "key-seqs" - "key-binding" "key-bindings"] - sexp)]] - ;; For arbitrary extensions, recognize anything else. - [symbolp &rest &or symbolp form] - ] - - ;; arithmetic - must be last since all parts are optional. - [[&optional [[&or "from" "downfrom" "upfrom"] form]] - [&optional [[&or "to" "downto" "upto" "below" "above"] form]] - [&optional ["by" form]] - ])) - -(def-edebug-spec loop-initial-final - (&or ["initially" - ;; [&optional &or "do" "doing"] ;; CLtL2 doesnt allow this. - &rest loop-non-atomic-expr] - ["finally" &or - [[&optional &or "do" "doing"] &rest loop-non-atomic-expr] - ["return" form]])) - -(def-edebug-spec loop-and-clause - (loop-clause &rest ["and" loop-clause])) - -(def-edebug-spec loop-clause - (&or - [[&or "while" "until" "always" "never" "thereis"] form] - - [[&or "collect" "collecting" - "append" "appending" - "nconc" "nconcing" - "concat" "vconcat"] form - [&optional ["into" loop-var]]] - - [[&or "count" "counting" - "sum" "summing" - "maximize" "maximizing" - "minimize" "minimizing"] form - [&optional ["into" loop-var]] - loop-type-spec] - - [[&or "if" "when" "unless"] - form loop-and-clause - [&optional ["else" loop-and-clause]] - [&optional "end"]] - - [[&or "do" "doing"] &rest loop-non-atomic-expr] - - ["return" form] - loop-initial-final - )) - -(def-edebug-spec loop-non-atomic-expr - ([¬ atom] form)) - -(def-edebug-spec loop-var - ;; The symbolp must be last alternative to recognize e.g. (a b . c) - ;; loop-var => - ;; (loop-var . [&or nil loop-var]) - ;; (symbolp . [&or nil loop-var]) - ;; (symbolp . loop-var) - ;; (symbolp . (symbolp . [&or nil loop-var])) - ;; (symbolp . (symbolp . loop-var)) - ;; (symbolp . (symbolp . symbolp)) == (symbolp symbolp . symbolp) - (&or (loop-var . [&or nil loop-var]) [gate symbolp])) - -(def-edebug-spec loop-type-spec - (&optional ["of-type" loop-d-type-spec])) - -(def-edebug-spec loop-d-type-spec - (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec)) - -;; cl-specs.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/cust-print.el --- a/lisp/edebug/cust-print.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,726 +0,0 @@ -;;; cust-print.el --- handles print-level and print-circle. - -;; Copyright (C) 1992 Free Software Foundation, Inc. - -;; Author: Daniel LaLiberte -;; Adapted-By: ESR -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;; LCD Archive Entry: -;; cust-print|Daniel LaLiberte|liberte@cs.uiuc.edu -;; |Handle print-level, print-circle and more. -;; |$Date: 1996/12/18 22:51:45 $|$Revision: 1.1.1.2 $| - -;; =============================== -;; $Header: /afs/informatik.uni-tuebingen.de/local/web/xemacs/xemacs-cvs/XEmacs/xemacs/lisp/edebug/Attic/cust-print.el,v 1.1.1.2 1996/12/18 22:51:45 steve Exp $ -;; $Log: cust-print.el,v $ -;; Revision 1.1.1.2 1996/12/18 22:51:45 steve -;; XEmacs 20.0 -- Beta 31 -;; -;; Revision 1.4 1994/03/23 20:34:29 liberte -;; * Change "emacs" to "original" - I just can't decide. -;; -;; Revision 1.3 1994/02/21 21:25:36 liberte -;; * Make custom-prin1-to-string more robust when errors occur. -;; * Change "internal" to "emacs". -;; -;; Revision 1.2 1993/11/22 22:36:36 liberte -;; * Simplified and generalized printer customization. -;; custom-printers is an alist of (PREDICATE . PRINTER) pairs -;; for any data types. The PRINTER function should print to -;; `standard-output' add-custom-printer and delete-custom-printer -;; change custom-printers. -;; -;; * Installation function now called install-custom-print. The -;; old name is still around for now. -;; -;; * New macro with-custom-print (added earlier) - executes like -;; progn but with custom-print activated temporarily. -;; -;; * Cleaned up comments for replacements of standardard printers. -;; -;; * Changed custom-prin1-to-string to use a temporary buffer. -;; -;; * Internal symbols are prefixed with CP::. -;; -;; * Option custom-print-vectors (added earlier) - controls whether -;; vectors should be printed according to print-length and -;; print-length. Emacs doesnt do this, but cust-print would -;; otherwise do it only if custom printing is required. -;; -;; * Uninterned symbols are treated as non-read-equivalent. -;; - - -;;; Commentary: - -;; This package provides a general print handler for prin1 and princ -;; that supports print-level and print-circle, and by the way, -;; print-length since the standard routines are being replaced. Also, -;; to print custom types constructed from lists and vectors, use -;; custom-print-list and custom-print-vector. See the documentation -;; strings of these variables for more details. - -;; If the results of your expressions contain circular references to -;; other parts of the same structure, the standard Emacs print -;; subroutines may fail to print with an untrappable error, -;; "Apparently circular structure being printed". If you only use cdr -;; circular lists (where cdrs of lists point back; what is the right -;; term here?), you can limit the length of printing with -;; print-length. But car circular lists and circular vectors generate -;; the above mentioned error in Emacs version 18. Version -;; 19 supports print-level, but it is often useful to get a better -;; print representation of circular and shared structures; the print-circle -;; option may be used to print more concise representations. - -;; There are three main ways to use this package. First, you may -;; replace prin1, princ, and some subroutines that use them by calling -;; install-custom-print so that any use of these functions in -;; Lisp code will be affected; you can later reset with -;; uninstall-custom-print. Second, you may temporarily install -;; these functions with the macro with-custom-print. Third, you -;; could call the custom routines directly, thus only affecting the -;; printing that requires them. - -;; Note that subroutines which call print subroutines directly will -;; not use the custom print functions. In particular, the evaluation -;; functions like eval-region call the print subroutines directly. -;; Therefore, if you evaluate (aref circ-list 0), where circ-list is a -;; circular list rather than an array, aref calls error directly which -;; will jump to the top level instead of printing the circular list. - -;; Uninterned symbols are recognized when print-circle is non-nil, -;; but they are not printed specially here. Use the cl-packages package -;; to print according to print-gensym. - -;; Obviously the right way to implement this custom-print facility is -;; in C or with hooks into the standard printer. Please volunteer -;; since I don't have the time or need. More CL-like printing -;; capabilities could be added in the future. - -;; Implementation design: we want to use the same list and vector -;; processing algorithm for all versions of prin1 and princ, since how -;; the processing is done depends on print-length, print-level, and -;; print-circle. For circle printing, a preprocessing step is -;; required before the final printing. Thanks to Jamie Zawinski -;; for motivation and algorithms. - - -;;; Code: -;;========================================================= - -;; If using cl-packages: - -'(defpackage "cust-print" - (:nicknames "CP" "custom-print") - (:use "el") - (:export - print-level - print-circle - - install-custom-print - uninstall-custom-print - custom-print-installed-p - with-custom-print - - custom-prin1 - custom-princ - custom-prin1-to-string - custom-print - custom-format - custom-message - custom-error - - custom-printers - add-custom-printer - )) - -'(in-package cust-print) - -(require 'backquote) - -;; Emacs 18 doesnt have defalias. -;; Provide def for byte compiler. -(defun defalias (symbol func) (fset symbol func)) -;; Better def when loaded. -(or (fboundp 'defalias) (fset 'defalias 'fset)) - - -;; Variables: -;;========================================================= - -;;(defvar print-length nil -;; "*Controls how many elements of a list, at each level, are printed. -;;This is defined by emacs.") - -(defvar print-level nil - "*Controls how many levels deep a nested data object will print. - -If nil, printing proceeds recursively and may lead to -max-lisp-eval-depth being exceeded or an error may occur: -`Apparently circular structure being printed.' -Also see `print-length' and `print-circle'. - -If non-nil, components at levels equal to or greater than `print-level' -are printed simply as `#'. The object to be printed is at level 0, -and if the object is a list or vector, its top-level components are at -level 1.") - - -(defvar print-circle nil - "*Controls the printing of recursive structures. - -If nil, printing proceeds recursively and may lead to -`max-lisp-eval-depth' being exceeded or an error may occur: -\"Apparently circular structure being printed.\" Also see -`print-length' and `print-level'. - -If non-nil, shared substructures anywhere in the structure are printed -with `#N=' before the first occurrence (in the order of the print -representation) and `#N#' in place of each subsequent occurrence, -where N is a positive decimal integer. - -There is no way to read this representation in standard Emacs, -but if you need to do so, try the cl-read.el package.") - - -(defvar custom-print-vectors nil - "*Non-nil if printing of vectors should obey print-level and print-length. - -For Emacs 18, setting print-level, or adding custom print list or -vector handling will make this happen anyway. Emacs 19 obeys -print-level, but not for vectors.") - - -;; Custom printers -;;========================================================== - -(defconst custom-printers nil - ;; e.g. '((symbolp . pkg::print-symbol)) - "An alist for custom printing of any type. -Pairs are of the form (PREDICATE . PRINTER). If PREDICATE is true -for an object, then PRINTER is called with the object. -PRINTER should print to `standard-output' using CP::original-princ -if the standard printer is sufficient, or CP::prin for complex things. -The PRINTER should return the object being printed. - -Don't modify this variable directly. Use `add-custom-printer' and -`delete-custom-printer'") -;; Should CP::original-princ and CP::prin be exported symbols? -;; Or should the standard printers functions be replaced by -;; CP ones in elisp so that CP internal functions need not be called? - -(defun add-custom-printer (pred printer) - "Add a pair of PREDICATE and PRINTER to `custom-printers'. -Any pair that has the same PREDICATE is first removed." - (setq custom-printers (cons (cons pred printer) - (delq (assq pred custom-printers) - custom-printers))) - ;; Rather than updating here, we could wait until CP::top-level is called. - (CP::update-custom-printers)) - -(defun delete-custom-printer (pred) - "Delete the custom printer associated with PREDICATE." - (setq custom-printers (delq (assq pred custom-printers) - custom-printers)) - (CP::update-custom-printers)) - - -(defun CP::use-custom-printer (object) - ;; Default function returns nil. - nil) - -(defun CP::update-custom-printers () - ;; Modify the definition of CP::use-custom-printer - (defalias 'CP::use-custom-printer - ;; We dont really want to require the byte-compiler. - ;; (byte-compile - (` (lambda (object) - (cond - (,@ (mapcar (function - (lambda (pair) - (` (((, (car pair)) object) - ((, (cdr pair)) object))))) - custom-printers)) - ;; Otherwise return nil. - (t nil) - ))) - ;; ) - )) - - -;; Saving and restoring emacs printing routines. -;;==================================================== - -(defun CP::set-function-cell (symbol-pair) - (defalias (car symbol-pair) - (symbol-function (car (cdr symbol-pair))))) - -(defun CP::original-princ (object &optional stream)) ; dummy def - -;; Save emacs routines. -(if (not (fboundp 'CP::original-prin1)) - (mapcar 'CP::set-function-cell - '((CP::original-prin1 prin1) - (CP::original-princ princ) - (CP::original-print print) - (CP::original-prin1-to-string prin1-to-string) - (CP::original-format format) - (CP::original-message message) - (CP::original-error error)))) - - -(defalias 'install-custom-print-funcs 'install-custom-print) -(defun install-custom-print () - "Replace print functions with general, customizable, Lisp versions. -The emacs subroutines are saved away, and you can reinstall them -by running `uninstall-custom-print'." - (interactive) - (mapcar 'CP::set-function-cell - '((prin1 custom-prin1) - (princ custom-princ) - (print custom-print) - (prin1-to-string custom-prin1-to-string) - (format custom-format) - (message custom-message) - (error custom-error) - )) - t) - -(defalias 'uninstall-custom-print-funcs 'uninstall-custom-print) -(defun uninstall-custom-print () - "Reset print functions to their emacs subroutines." - (interactive) - (mapcar 'CP::set-function-cell - '((prin1 CP::original-prin1) - (princ CP::original-princ) - (print CP::original-print) - (prin1-to-string CP::original-prin1-to-string) - (format CP::original-format) - (message CP::original-message) - (error CP::original-error) - )) - t) - -(defalias 'custom-print-funcs-installed-p 'custom-print-installed-p) -(defun custom-print-installed-p () - "Return t if custom-print is currently installed, nil otherwise." - (eq (symbol-function 'custom-prin1) (symbol-function 'prin1))) - -(put 'with-custom-print-funcs 'edebug-form-spec '(body)) -(put 'with-custom-print 'edebug-form-spec '(body)) - -(defalias 'with-custom-print-funcs 'with-custom-print) -(defmacro with-custom-print (&rest body) - "Temporarily install the custom print package while executing BODY." - (` (unwind-protect - (progn - (install-custom-print) - (,@ body)) - (uninstall-custom-print)))) - - -;; Lisp replacements for prin1 and princ, and for some subrs that use them -;;=============================================================== -;; - so far only the printing and formatting subrs. - -(defun custom-prin1 (object &optional stream) - "Output the printed representation of OBJECT, any Lisp object. -Quoting characters are printed when needed to make output that `read' -can handle, whenever this is possible. -Output stream is STREAM, or value of `standard-output' (which see). - -This is the custom-print replacement for the standard `prin1'. It -uses the appropriate printer depending on the values of `print-level' -and `print-circle' (which see)." - (CP::top-level object stream 'CP::original-prin1)) - - -(defun custom-princ (object &optional stream) - "Output the printed representation of OBJECT, any Lisp object. -No quoting characters are used; no delimiters are printed around -the contents of strings. -Output stream is STREAM, or value of `standard-output' (which see). - -This is the custom-print replacement for the standard `princ'." - (CP::top-level object stream 'CP::original-princ)) - - -(defun custom-prin1-to-string (object) - "Return a string containing the printed representation of OBJECT, -any Lisp object. Quoting characters are used when needed to make output -that `read' can handle, whenever this is possible. - -This is the custom-print replacement for the standard `prin1-to-string'." - (let ((buf (get-buffer-create " *custom-print-temp*"))) - ;; We must erase the buffer before printing in case an error - ;; occured during the last prin1-to-string and we are in debugger. - (save-excursion - (set-buffer buf) - (erase-buffer)) - ;; We must be in the current-buffer when the print occurs. - (custom-prin1 object buf) - (save-excursion - (set-buffer buf) - (buffer-string) - ;; We could erase the buffer again, but why bother? - ))) - - -(defun custom-print (object &optional stream) - "Output the printed representation of OBJECT, with newlines around it. -Quoting characters are printed when needed to make output that `read' -can handle, whenever this is possible. -Output stream is STREAM, or value of `standard-output' (which see). - -This is the custom-print replacement for the standard `print'." - (CP::original-princ "\n" stream) - (custom-prin1 object stream) - (CP::original-princ "\n" stream)) - - -(defun custom-format (fmt &rest args) - "Format a string out of a control-string and arguments. -The first argument is a control string. It, and subsequent arguments -substituted into it, become the value, which is a string. -It may contain %s or %d or %c to substitute successive following arguments. -%s means print an argument as a string, %d means print as number in decimal, -%c means print a number as a single character. -The argument used by %s must be a string or a symbol; -the argument used by %d, %b, %o, %x or %c must be a number. - -This is the custom-print replacement for the standard `format'. It -calls the emacs `format' after first making strings for list, -vector, or symbol args. The format specification for such args should -be `%s' in any case, so a string argument will also work. The string -is generated with `custom-prin1-to-string', which quotes quotable -characters." - (apply 'CP::original-format fmt - (mapcar (function (lambda (arg) - (if (or (listp arg) (vectorp arg) (symbolp arg)) - (custom-prin1-to-string arg) - arg))) - args))) - - -(defun custom-message (fmt &rest args) - "Print a one-line message at the bottom of the screen. -The first argument is a control string. -It may contain %s or %d or %c to print successive following arguments. -%s means print an argument as a string, %d means print as number in decimal, -%c means print a number as a single character. -The argument used by %s must be a string or a symbol; -the argument used by %d or %c must be a number. - -This is the custom-print replacement for the standard `message'. -See `custom-format' for the details." - ;; It doesn't work to princ the result of custom-format as in: - ;; (CP::original-princ (apply 'custom-format fmt args)) - ;; because the echo area requires special handling - ;; to avoid duplicating the output. - ;; CP::original-message does it right. - (apply 'CP::original-message fmt - (mapcar (function (lambda (arg) - (if (or (listp arg) (vectorp arg) (symbolp arg)) - (custom-prin1-to-string arg) - arg))) - args))) - - -(defun custom-error (fmt &rest args) - "Signal an error, making error message by passing all args to `format'. - -This is the custom-print replacement for the standard `error'. -See `custom-format' for the details." - (signal 'error (list (apply 'custom-format fmt args)))) - - - -;; Support for custom prin1 and princ -;;========================================= - -;; Defs to quiet byte-compiler. -(defvar circle-table) -(defvar CP::current-level) - -(defun CP::original-printer (object)) ; One of the standard printers. -(defun CP::low-level-prin (object)) ; Used internally. -(defun CP::prin (object)) ; Call this to print recursively. - -(defun CP::top-level (object stream emacs-printer) - ;; Set up for printing. - (let ((standard-output (or stream standard-output)) - ;; circle-table will be non-nil if anything is circular. - (circle-table (and print-circle - (CP::preprocess-circle-tree object))) - (CP::current-level (or print-level -1))) - - (defalias 'CP::original-printer emacs-printer) - (defalias 'CP::low-level-prin - (cond - ((or custom-printers - circle-table - print-level ; comment out for version 19 - ;; Emacs doesn't use print-level or print-length - ;; for vectors, but custom-print can. - (if custom-print-vectors - (or print-level print-length))) - 'CP::print-object) - (t 'CP::original-printer))) - (defalias 'CP::prin - (if circle-table 'CP::print-circular 'CP::low-level-prin)) - - (CP::prin object) - object)) - - -(defun CP::print-object (object) - ;; Test object type and print accordingly. - ;; Could be called as either CP::low-level-prin or CP::prin. - (cond - ((null object) (CP::original-printer object)) - ((CP::use-custom-printer object) object) - ((consp object) (CP::list object)) - ((vectorp object) (CP::vector object)) - ;; All other types, just print. - (t (CP::original-printer object)))) - - -(defun CP::print-circular (object) - ;; Printer for `prin1' and `princ' that handles circular structures. - ;; If OBJECT appears multiply, and has not yet been printed, - ;; prefix with label; if it has been printed, use `#N#' instead. - ;; Otherwise, print normally. - (let ((tag (assq object circle-table))) - (if tag - (let ((id (cdr tag))) - (if (> id 0) - (progn - ;; Already printed, so just print id. - (CP::original-princ "#") - (CP::original-princ id) - (CP::original-princ "#")) - ;; Not printed yet, so label with id and print object. - (setcdr tag (- id)) ; mark it as printed - (CP::original-princ "#") - (CP::original-princ (- id)) - (CP::original-princ "=") - (CP::low-level-prin object) - )) - ;; Not repeated in structure. - (CP::low-level-prin object)))) - - -;;================================================ -;; List and vector processing for print functions. - -(defun CP::list (list) - ;; Print a list using print-length, print-level, and print-circle. - (if (= CP::current-level 0) - (CP::original-princ "#") - (let ((CP::current-level (1- CP::current-level))) - (CP::original-princ "(") - (let ((length (or print-length 0))) - - ;; Print the first element always (even if length = 0). - (CP::prin (car list)) - (setq list (cdr list)) - (if list (CP::original-princ " ")) - (setq length (1- length)) - - ;; Print the rest of the elements. - (while (and list (/= 0 length)) - (if (and (listp list) - (not (assq list circle-table))) - (progn - (CP::prin (car list)) - (setq list (cdr list))) - - ;; cdr is not a list, or it is in circle-table. - (CP::original-princ ". ") - (CP::prin list) - (setq list nil)) - - (setq length (1- length)) - (if list (CP::original-princ " "))) - - (if (and list (= length 0)) (CP::original-princ "...")) - (CP::original-princ ")")))) - list) - - -(defun CP::vector (vector) - ;; Print a vector according to print-length, print-level, and print-circle. - (if (= CP::current-level 0) - (CP::original-princ "#") - (let ((CP::current-level (1- CP::current-level)) - (i 0) - (len (length vector))) - (CP::original-princ "[") - - (if print-length - (setq len (min print-length len))) - ;; Print the elements - (while (< i len) - (CP::prin (aref vector i)) - (setq i (1+ i)) - (if (< i (length vector)) (CP::original-princ " "))) - - (if (< i (length vector)) (CP::original-princ "...")) - (CP::original-princ "]") - )) - vector) - - - -;; Circular structure preprocessing -;;================================== - -(defun CP::preprocess-circle-tree (object) - ;; Fill up the table. - (let (;; Table of tags for each object in an object to be printed. - ;; A tag is of the form: - ;; ( ) - ;; The id-number is generated after the entire table has been computed. - ;; During walk through, the real circle-table lives in the cdr so we - ;; can use setcdr to add new elements instead of having to setq the - ;; variable sometimes (poor man's locf). - (circle-table (list nil))) - (CP::walk-circle-tree object) - - ;; Reverse table so it is in the order that the objects will be printed. - ;; This pass could be avoided if we always added to the end of the - ;; table with setcdr in walk-circle-tree. - (setcdr circle-table (nreverse (cdr circle-table))) - - ;; Walk through the table, assigning id-numbers to those - ;; objects which will be printed using #N= syntax. Delete those - ;; objects which will be printed only once (to speed up assq later). - (let ((rest circle-table) - (id -1)) - (while (cdr rest) - (let ((tag (car (cdr rest)))) - (cond ((cdr tag) - (setcdr tag id) - (setq id (1- id)) - (setq rest (cdr rest))) - ;; Else delete this object. - (t (setcdr rest (cdr (cdr rest)))))) - )) - ;; Drop the car. - (cdr circle-table) - )) - - - -(defun CP::walk-circle-tree (object) - (let (read-equivalent-p tag) - (while object - (setq read-equivalent-p - (or (numberp object) - (and (symbolp object) - ;; Check if it is uninterned. - (eq object (intern-soft (symbol-name object))))) - tag (and (not read-equivalent-p) - (assq object (cdr circle-table)))) - (cond (tag - ;; Seen this object already, so note that. - (setcdr tag t)) - - ((not read-equivalent-p) - ;; Add a tag for this object. - (setcdr circle-table - (cons (list object) - (cdr circle-table))))) - (setq object - (cond - (tag ;; No need to descend since we have already. - nil) - - ((consp object) - ;; Walk the car of the list recursively. - (CP::walk-circle-tree (car object)) - ;; But walk the cdr with the above while loop - ;; to avoid problems with max-lisp-eval-depth. - ;; And it should be faster than recursion. - (cdr object)) - - ((vectorp object) - ;; Walk the vector. - (let ((i (length object)) - (j 0)) - (while (< j i) - (CP::walk-circle-tree (aref object j)) - (setq j (1+ j)))))))))) - - -;; Example. -;;======================================= - -'(progn - (progn - ;; Create some circular structures. - (setq circ-sym (let ((x (make-symbol "FOO"))) (list x x))) - (setq circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f)) - (setcar (nthcdr 3 circ-list) circ-list) - (aset (nth 2 circ-list) 2 circ-list) - (setq dotted-circ-list (list 'a 'b 'c)) - (setcdr (cdr (cdr dotted-circ-list)) dotted-circ-list) - (setq circ-vector (vector 1 2 3 4 (list 'a 'b 'c 'd) 6 7)) - (aset circ-vector 5 (make-symbol "-gensym-")) - (setcar (cdr (aref circ-vector 4)) (aref circ-vector 5)) - nil) - - (install-custom-print) - ;; (setq print-circle t) - - (let ((print-circle t)) - (or (equal (prin1-to-string circ-list) "#1=(a b [1 2 #1# 4] #1# e f)") - (error "circular object with array printing"))) - - (let ((print-circle t)) - (or (equal (prin1-to-string dotted-circ-list) "#1=(a b c . #1#)") - (error "circular object with array printing"))) - - (let* ((print-circle t) - (x (list 'p 'q)) - (y (list (list 'a 'b) x 'foo x))) - (setcdr (cdr (cdr (cdr y))) (cdr y)) - (or (equal (prin1-to-string y) "((a b) . #1=(#2=(p q) foo #2# . #1#))" - ) - (error "circular list example from CL manual"))) - - (let ((print-circle nil)) - ;; cl-packages.el is required to print uninterned symbols like #:FOO. - ;; (require 'cl-packages) - (or (equal (prin1-to-string circ-sym) "(#:FOO #:FOO)") - (error "uninterned symbols in list"))) - (let ((print-circle t)) - (or (equal (prin1-to-string circ-sym) "(#1=FOO #1#)") - (error "circular uninterned symbols in list"))) - - (uninstall-custom-print) - ) - -(provide 'cust-print) - -;;; cust-print.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/custom-load.el --- a/lisp/edebug/custom-load.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -;;; custom-load.el --- automatically extracted custom dependencies - - -;;; Code: - -(custom-add-loads 'lisp '("edebug")) -(custom-add-loads 'edebug '("edebug")) - -;;; custom-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/edebug-cl-read.el --- a/lisp/edebug/edebug-cl-read.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -;;; edebug-cl-read.el --- Edebug reader macros for use with cl-read. - -;; Copyright (C) 1993 Daniel LaLiberte -;; Author: Daniel LaLiberte -;; Keywords: lisp, tools, maint - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; LCD Archive Entry: -;; edebug-cl-read.el|Daniel LaLiberte|liberte@cs.uiuc.edu -;; |Edebug reader macros for cl-read.el -;; |$Date: 1996/12/18 22:51:45 $|$Revision: 1.1.1.2 $|~/modes/edebug-cl-read.el| - -;; If you use cl-read.el and want to use edebug with any code -;; in a file written with CL read syntax, then you need to use this -;; package. - -;; To Do: -;; Handle shared structures, but this is not normally used in executable code. - -;; Read-time evaluation shouldn't be used in a form argument since -;; there is no way to instrument the result of the evaluation, and -;; no way to tell Edebug not to try. - -;; Need to mangle all local variable names that might be visible to -;; eval, e.g. stream, char. Alternatively, packages could hide them. - -;;; Code: - -(require 'cl) -;; For byte compiling cl-read is needed. -;; But edebug-cl-read should not even be loaded unless cl-read already is. -(require 'cl-read) - -(provide 'edebug-cl-read) -;; Do the above provide before the following require to avoid load loop. -(require 'edebug) - -(defvar reader::stack) - -;; The following modifications of reader functions -;; could be done via advice. But we need to switch between -;; edebug versions and originals frequently. Also advice.el -;; doesn't support advising anonymous functions. - -(defun edebug-reader::read-sexp-func (point func) - ;; dummy def - ) - -(defvar edebug-read-dotted-list) - -(defun edebug-read-sexp-func (point func) - "Edebug offset storing is happening." - (edebug-storing-offsets point - (let (edebug-read-dotted-list) - (edebug-reader::read-sexp-func point func)))) - -(defun edebug-end-list-handler (stream char) - ;; If the dotted form is a list, signal to offset routines. - (setq edebug-read-dotted-list (listp (car reader::stack))) - (edebug-reader::end-list-handler stream char)) - - -;;========================================================================= -;; Redefine the edebug reader to check whether CL syntax is active. -;; This might be a little cleaner using advice. - -(defvar edebug-reading-with-cl-read nil) - -(or (fboundp 'edebug-original-read-storing-offsets) - (defalias 'edebug-original-read-storing-offsets - (symbol-function 'edebug-read-storing-offsets))) - -(defun edebug-read-storing-offsets (stream) - ;; Read a sexp from STREAM. - ;; STREAM is limited to the current buffer. - ;; Create a parallel offset structure as described in doc for edebug-offsets. - ;; This version, from edebug-cl-read, uses cl-read. - (if (not cl-read-active) - ;; Use the reader for standard Emacs Lisp. - (edebug-original-read-storing-offsets stream) - - ;; Use cl-read with edebug hooks. - (if edebug-reading-with-cl-read nil - ;; Only do this if it's not already been done, else it loops. - (fset 'edebug-reader::read-sexp-func - (symbol-function 'reader::read-sexp-func)) - (fset 'reader::read-sexp-func 'edebug-read-sexp-func) - (fset 'edebug-reader::end-list-handler (get-macro-character ?\))) - (set-macro-character ?\) 'edebug-end-list-handler))) - (unwind-protect - (let ((edebug-reading-with-cl-read t)) - (reader::read stream)) - (if edebug-reading-with-cl-read nil - (set-macro-character - ?\) (symbol-function 'edebug-reader::end-list-handler)) - (fset 'reader::read-sexp-func - (symbol-function 'edebug-reader::read-sexp-func))))) - diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/edebug-history --- a/lisp/edebug/edebug-history Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,333 +0,0 @@ -@c =================================================================== -@node Revision History, Index, Todo List, Top -@section Revision History - -Here is a summary of changes to edebug recorded in the RCS log, in -reverse chronological order. - -Revision 2.9 1993/02/04 22:40:58 liberte -Fix handling of 0 and t edebug-form-specs. - -Remove loop for consecutive special specs to simplify code. - -Fix [&optional specs] again. - -Bug: [&rest specs] still broken. - -Bug: nested definitions may have problems still - let me know. - -New variable edebug-debugger holds name of debugger for errors or quit. - -Unrestore edebug-buffer's window-point after edebug display. -Needed in addition to setting the buffer point -because otherwise quitting doesnt leave point as is. -But doing it causes point not to be restored other times. -Let me know if there are problems. - -Fix zmacs-regions typo for lemacs. - -Revision 2.8 1993/01/13 18:34:19 liberte -Support edebugging top-level forms and generalize handling -of defining forms. - -Rename edebug-defun to edebug-eval-top-level-form. -edebug-defun still points to the latter. - -Rename edebug-all-defuns to edebug-all-defs. - -Add edebug-all-forms option and command. - -Add edebug-continue-kbd-macro option. - -Stop defining epoch::version. - -Rename def-edebug-form-spec to def-edebug-spec. Arguments are unevaluated. - -edebug-form-spec supports indirection. List specs may now -contain body, &define, name, arglist, def-body, def-form, and strings. - -While parsing, commit to alternative after matching a symbol. - -Fix nested &optional handling. - -Improve syntax error reporting. - -Use edebug-form-specs for many Emacs special-forms: defun, defmacro, -interactive, condition-case, cond, as well as lambda forms and -functions that take function arguments. Define specs for all cl.el -macros. - -Fix printing of window objects so they show the correct buffer. - -Numerous display fixes that are too complex to explain. - -Display frequency counts along with coverage data by inserting comment -lines. - -Add global break condition. - -Add "next" mode to stop only after expression evaluation. -Add top-level-nonstop to stop no more. - -Add time argument to edebug-bounce-point. - -Allow editing of previous breakpoint condition. - -Fix edebug-step-in. - -Clean up the backtrace display better. - -Support Lucid Emacs command events. - - -Revision 2.7 92/03/23 - -Fix edebug-get-displayed-buffer-points to actually change buffers. - -Restore current buffer in edebug-set-buffer-points - -Use epoch::version instead of edebug-epoch-running. - -Apparently we need to set-buffer in edebug-pop-to-buffer, -even after select-window. - -Define dynamically bound variables to quite byte-compiler, -but leave them unbound to cause runtime error if used improperly. - -Fix other problems with window-start, current-buffer, and -edebug-outside-excursion. - -Revision 2.6 92/03/19 -Disable edebug-save-point. Now point of source code buffers is always -saved, mark is never saved, and window-start is always saved. - -Change name of edebug-save-buffer-points to -edebug-save-displayed-buffer-points. Also, if non-nil, only displayed -buffer points are saved. - -Restructure definition of epoch specific functions so there is no -overhead for non-epoch use. - -Add support for custom-print functions to handle print-level and -print-circle. Use edebug-prin* functions instead of standard -print functions. - -Yet another change of the instrumenting scheme: -edebug-enter gets a lambda form which can be byte-compiled; -edebug-after gets the after expression index from edebug-before which -is given the before expression index. (Perhaps it is false economy to -avoid the after expression index.) edebug-after also gets the -evaluated expression result, so no explicit evals need be done. - -Most of edebug-defun was moved to edebug-func-form which also -handles embedded defuns. - -Add functions edebug-forms and edebug-sexps. - -Rename edebug-list to edebug-list-form. - -Use edebug-form-specs for all special forms. The spec may now be -a function which is called to process args. Added -form to -the names of special form parser functions. - -Rename edebug-form-parser to edebug-interpret-form-spec. Add handling -of [...], function spec, and backtracking. &optional now only applies -to one following spec. Fixed some other bugs. - -Added macro def-edebug-form-spec for convenience, and to convert -0 and t values to edebug-forms and edebug-sexps. - -Add edebug-form-specs for mapcar, mapconcat, mapatoms, apply, and funcall -that all use the new function spec. - -Rebuilt edebug-read-sexp to be simpler, faster, and more complete. - -Accummulate frequencies of expression evaluation, displayable -with edebug-display-freq-count. - -No longer do save-restriction since edebug's eval-region doesnt narrow. - -Numerous other display changes related to source code buffer's -point and window-start. - -Add -mode to the names of mode changing functions. - -Set debugger to edebug-debug while inside edebug - it's almost -always useful inside, and not useful outside of edebug. - -Add edebug-trace function to output FMT with ARGS to *edebug-trace* buffer. - -Other changes I've forgotten. - -Revision 2.5 91/07/25 - -Doc string cleanup. - -If edebug-form-spec is t, evaluate all arguments. - -If edebug-form-spec is 0, evaluate no arguments. - -If edebug-form-spec is nil, evaluate macro args according - to edebug-eval-macro-args. - -Save the outside value of executing macro. - -Save and restore the outside restriction. - -Dont force update for go and Go-nonstop. - -Save and restore last-command-char, last-command, - this-command, last-input-char. - -For epoch, do epoch::dispatch-events before sit-for - and input-pending-p since X events could interfere. - -Warn about unsetting non-existent breakpoint. - -Fix edebug-forward-sexp with prefix arg. - -Add edebug-step-out to exit from current sexp. - -Revision 2.4 91/03/18 -Force update after go or Go-nonstop modes, so overlay arrow is correct. - -Support debug-on-quit. Remove edebug-on-error. - -Fix edebug-anonymous. Bug found by jackr@wpd.sgi.com (Jack Repenning). - -Don't discard-input anymore. Easier to change modes this way. - -Fix max-lisp-eval-depth and max-specpdl-size incrementing. - -Save and restore points in all buffers, if - edebug-save-buffer-points is non-nil. Expensive! - Bug caught by wolfgang@wsrcc.com (Wolfgang S. Rupprecht) - -Save standard-output and standard-input in edebug-recursive-edit - so that edebug-outside-excursion can restore them. - -Call set-buffer in edebug-pop-to-buffer since - select-window does not do that. - -Fix edebug's eval-defun to remember current buffer inside evaluations - and to evaluate top-level forms. Found by Jamie Zawinski. - -Add edebug-interactive-entry to support interactive forms with - non-string arg. Bug found by Jack Repenning. - -Simplify edebug-restore-match-data to just store-match-data. - Motivated by linus@lysator.liu.se. - -Move the match-data call to before the outside - buffer is changed, since it assumes that. - -Revision 2.3 91/01/17 - -Fix bug found by hollen@megatek.uucp. - Current buffer was not being restored. - -Call edebug with (edebug begin end 'exp) - and add additional wrapper around body of functions: - (edebug-enter function body). - -Make &optional only apply to immediate next arg - in edebug-interpret-form-spec (was edebug-macro-parser). - -Catch debug errors with edebug. Yeah! - -Reset edebug-mode on first function entry. Yeah! - Motivated by Dion Hollenbeck. - -Add the missing bindings to the global-edebug-map. - -eval-current-buffer now uses eval-region. - -eval-region now does not narrow region. - Narrowing was the cause of the window-start being set wrong. - -Reset edebug-mode only on - first entry of any function at each recursive-edit level. - -Add edebug-backtrace, to generate cleaned up - backtrace. It doesnt "work" like the debug backtrace, however. - -Require reselecting outside window even if - quit occurs, otherwise save-excursions may restore - buffer to the wrong window. - -Revision 2.2 90/11/26 - -Shadow eval-defun and eval-region. Toggle - edebugging with edebug-all-defuns. - -Call edebug with (edebug 'function begin end 'exp) - Suggested by Jamie Zawinski . - -Add edebug-interpret-form-spec to process macro args. - Motivated by Darryl Okahata darrylo@hpnmxx.hp.com. - -Fix by Roland McGrath - to wrap body of edebug-save-restriction in progn. - -Fix by Darryl Okahata - to add (set-window-hscroll (selected-window) 0) to - edebug-pop-to-buffer. - -Revision 2.1 90/11/16 - -Clean up. - -Add edebug-form-spec to edebug macro calls. Thanks to Joe Wells. - -edebug-forward-sexp uses step mode if no forward-sexp. - -Revision 2.0 90/11/14 22:30:54 liberte - -Handle lambda forms, function, interactive evals, defmacro. - -Clean up display for Epoch - save and restore screen configurations. - Note: epoch 3.2 broke set-window-configuration. - Also, sit-for pauses do not always work in epoch. - -Display evaluations window. - -Display result after expression evaluation. - Thanks to discussions with Shinichirou Sugou. - -Conditional and temporary breakpoints. - -Change "continue" to "go" mode and add different "continue" mode. - -Option to stop before symbols. - -Fix by: Glen Ditchfield gjditchfield@violet.uwaterloo.ca -to handle ?# type chars. - - -Revision 1.5 89/05/10 -Fix condition-case expression lists. - -Reorganize edebug. - -Revision 1.4 89/02/14 -Fix broken breakpointing. - -Temporarily widen elisp buffer during edebug. - -Revision 1.3 89/01/30 -More bug fixes for cond and let. - -Another parsing fix backquote. - -Fix for lambda forms inside defuns. - -Leave point at syntax error, mark at starting position. - -Revision 1.2 88/11/28 -Bug fixes: cond construct didnt execute. - () in sexp list didnt parse - () as variable in condition-case didnt parse. - -Revision 1.1 88/11/28 -Initial revision - diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/edebug-test.el --- a/lisp/edebug/edebug-test.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1189 +0,0 @@ -;; Some tests for edebug. - -;;======================= -;; Reading tests. - -(testing (one two) three) - -(progn '(testing)) - -(a . (b . c)) - -(a . "test") - -(a . (b . nil)) - -(a . [one two three]) - -;;=========================== -;; Backquote test - -(defun test () - (macroexpand '(` ((, (a)) . (, test)))) -) -(test) - -(progn (` ((, (point)) . (, (point))))) -(` (, (point))) - -(defun test () -(message "%d" 999999) - -(defun test1 () - - (progn - (defun test () - (message "%d" 99999)) - (test) - ) - - ) -(test1) -(test) - -(eval (edebug-` (append [(, (point)) (, (point))] nil))) -(eval (edebug-` (append (, (point)) (, (point)) nil))) - -(eval (progn (edebug-` (edebug-` (, '(, (point))))))) - -(eval (edebug-` (let (((, 'a) 'b)) - (message "%s" a)))) - -(defun test () - -(let ((r '(union x y))) - (` (` (foo (, '(, r)))))) -) - -(defun test () - (let ((a '(one two))) a)) - -(def-edebug-spec test-func (sexp &rest def-form)) - -(setq edebug-unwrap-results t) -(setq edebug-unwrap-results nil) - -(defmacro test-func (func &rest args) - (edebug-` ((, func) (,@ args)))) - -(test-func message (concat "hi%s" "there") (+ 1 2)) - -(defmacro test-progn (&rest body) - (edebug-` (progn (,@ body)))) - -(def-edebug-spec test-progn (&rest def-form)) - -(test-progn - (message "testing")) - - -;;================= -;; Testing read syntax. - -(format "testing %s %s %s" 1 2 (+ 1 2)) - -(defun test-syntax () - (setq mode-line-stuff'("draft(%b) ^C^S(end) ^C^Q(uit) ^C^K(ill)")) -;; (re-search-forward "[.?!][])""']*$" nil t) -;; (let (test) - ) -) - -(test-syntax) - -(let ()) -;;==================== -;; Testing function - -(defun foo (x) - (mapconcat (function identity) x ", ")) - -(defun foo (x) - (mapconcat 'identity x ", ")) - -(defun foo (x) - (mapconcat (function (lambda (x) x)) x ", ")) - -(require 'cl) - -(defun foo (x) - (mapconcat (function* (lambda (x &optional (y (1+ x)) &key xyz) x)) x ", ")) - -(defun foo (x) - (mapconcat '(lambda (x) x) x ", ")) - -(foo '(1 2 3)) - -(apply 'identity one two) - -(defun test1 (arg) - arg) - -(def-edebug-spec test1 - (form)) -(setq x 5) -(test1 (+ x 2)) - - (("test1" test1))) - -(def-edebug-spec test1 - (&define sexp form)) - -(test (test1 xyz (message "jfdjfd"))) - -;;==================== -;; Anonymous function test -(defun hej (arg) - "docstring" - (interactive (list 2)) - ((lambda (luttr &rest params) - (apply luttr luttr params)) - (function (lambda (self n) - (edebug-trace "n: %s" n) - (if (= n 5) (edebug nil "n is 5")) - (edebug-tracing "cond" - (cond - ((= 0 n) 1) - (t (* n (funcall self self (1- n)))))))) - 11)) - -(defun hej-test () - (interactive) - (message - "testing") - (hej edebug-execution-mode) - ) -(hej-test) - -(defun lambda-test () - ((lambda (arg) arg) 'xyz)) -(lambda-test) - -(defun test () - "doc string - (with left paren on start of line)" - - 1) - - -(progn - (save-window-excursion - (split-window) - (split-window) - (setq w (next-window))) - (edebug-window-live-p w)) - - -;;==================== -;; Test edebugging top-level-forms - -(def-edebug-spec test nil) -(let ((arg (list 'a 'b 'c))) - (defun test (arg) - arg) - (test arg)) - - -(fset 'emacs-setq (symbol-function 'setq)) - -(defmacro my-setq (&rest args) - (while args - (set (car args) (eval (car (cdr args)))) - (setq args (cdr (cdr args))))) - -(defmacro test-macro (&rest args) - (cons 'list args)) -(def-edebug-spec test-macro 0) - -(defun test () - (test-macro (message "testing"))) -(test) - -(defun test () - (message "someting") - (function (lambda () - (message "something else"))) - ) - -(funcall (test)) - -;;==================== -;; Test for and inc -(def-edebug-spec for - (symbolp ["from" def-form ["to" def-form] ["do" &rest def-form]])) - - ;; (symbolp ['from form ['to form] ['do &rest form]]) - -(inc x) -(defmacro inc (var) - (list 'setq var (list '1+ var))) - -(defmacro for (var from init to final do &rest body) - (let ((tempvar (make-symbol "max"))) - (edebug-` (let (((, var) (, init)) - ((, tempvar) (, final))) - (while (<= (, var) (, tempvar)) - (,@ body) - (inc (, var))))))) - -(defun test-for (one two) - (for i from one to two do - (message "%s" i)) - ) - -(let ((n 5)) - (for i from n to (* n (+ n 1)) do - (message "%s" i))) - -(test-for 3 10) - -;;==================== -;; Test condition-case -(def-edebug-spec condition-case - (symbolp - form - &rest (symbolp &optional form))) - -(setq edebug-on-signal '(error)) - -(defun test-condition-case () - (condition-case err - (signal 'error '(oh)) - (error (message "error: %s" err)) - )) -(test-condition-case) - -(require 'cl) - -;;============= -;; lexical let - -(defun test-lexical () - (funcall (lexical-let ((xyz 123)) - (function (lambda (arg) (+ arg xyz)))) - 456)) -(test-lexical) - -;;==================== -;; case test. -(defun test-case (one) - (case one - ((one) (message "(one)")) - ("one" (message "one")) - ('one (message "'one")) - )) - -(test-case 'one) - -;;==================== -;; Test of do from cl.el - -(defun list-reverse (list) - (do ((x list (cdr x)) - (y nil (cons (car x) y))) - ((endp x) y) - (message "x: %s y: %s" x y) - )) - - -(list-reverse '(testing one two three)) - -(defmacro test-backquote (arg list) - (edebug-` - (progn - (message "%s %s" (, arg) (, list)) - (mapcar (function (lambda (arg1) - (message "%s %s" arg1 (, arg)))) (, list))))) - -(def-edebug-spec test-backquote (def-form def-form)) -(test-backquote (symbol-name 'something) (list 1 2 3)) - - -(defmacro dired-map-over-marks (body arg &optional show-progress) - (edebug-` (prog1 - (let (buffer-read-only case-fold-search found results) - (if (, arg) - (if (integerp (, arg)) - (progn;; no save-excursion, want to move point. - (dired-repeat-over-lines - (, arg) - (function (lambda () - (if (, show-progress) (sit-for 0)) - (setq results (cons (, body) results))))) - (if (< (, arg) 0) - (nreverse results) - results)) - ;; non-nil, non-integer ARG means use current file: - (list (, body))) - (let ((regexp (dired-marker-regexp)) next-position) - (save-excursion - (goto-char (point-min)) - ;; remember position of next marked file before BODY - ;; can insert lines before the just found file, - ;; confusing us by finding the same marked file again - ;; and again and... - (setq next-position (and (re-search-forward regexp nil t) - (point-marker)) - found (not (null next-position))) - (while next-position - (goto-char next-position) - (if (, show-progress) (sit-for 0)) - (setq results (cons (, body) results)) - ;; move after last match - (goto-char next-position) - (forward-line 1) - (set-marker next-position nil) - (setq next-position (and (re-search-forward regexp nil t) - (point-marker))))) - (if found - results - (list (, body)))))) - ;; save-excursion loses, again - (dired-move-to-filename)))) - - -(def-edebug-spec dired-map-over-marks (&rest def-form)) - -(dired-map-over-marks - (message "here") (+ 1 2) t) - -;;==================== -;; circular structure test - -(edebug-install-custom-print) -(edebug-uninstall-custom-print) - -(setq a '(1 2)) -(progn - (edebug-install-custom-print) - (setq a '(1 2)) - (setcar a a)) - -(defun test () - (with-custom-print - (format "%s" (setcar a a))))) -(test) -(setcdr a a) -(let ((b a)) b) - -(with-custom-print - (let ((print-circle t) - (circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f))) - (setcar (nthcdr 3 circ-list) circ-list) - (aset (nth 2 circ-list) 2 circ-list) - (prin1-to-string circ-list))) - -;;==================== -;; interactive-p test -(defun test-interactive () - (interactive) - (interactive-p)) - -(test-interactive) -(call-interactively 'test-interactive) - - -;;==================== -;; test several things: -;; - nested defun. -;; - display scrolling. - - -(defmacro testmacro () - '(interactive-p)) - -(call-interactively 'testing1) -(testing1 9) - -(defun testing1 (arg) - (interactive (list 3)) - (message "%s" (interactive-p)) (sit-for 2) - (edebug-trace "interactive: %s" (testmacro)) - (defun testing1-1 () - (testing1 2)) -;; (custom-message "%s" arg "extra") - (current-buffer) - (selected-window) - (while (< 0 (setq arg (1- arg))) - arg - arg - arg - arg - arg - arg - arg - arg - arg ; middle - arg - arg - arg - arg - arg - arg - arg - arg - arg - arg ; jump - arg - arg - arg - arg - arg - arg - arg - arg - arg - arg - arg - arg - arg -)) -(edebug-trace-display "*testing*" "one") -(edebug-tracer "one\n") - -(testing1 a) -(call-interactively 'testing1) -(testing1 2) - -(testing1-1) - - -(defmacro testmacro () - (interactive) - '(one)) - -(defun testing2 () - (let* ((buf (get-buffer-create "testing")) - (win (get-buffer-window buf))) - (testing1 1) - (window-point win) - (window-point win) - -;; (read-stream-char buf) - )) - -(testing2) - - -(defun testing3 () - (save-excursion - (set-buffer (get-buffer-create "*testing*")) - (current-buffer) - (point) - (forward-char 1) - )) -(testing3) - - -;;==================== -;; anonymous function test -(defun testanon (arg) - (mapcar '(lambda (x) x) arg) - (mapcar (function (lambda (x) x)) arg) - (mapcar (function testing3 ) arg) - ) - -(testanon '(1 2 3)) - -;;==================== -;; upward funarg test - -(defmacro lambda (&rest args) - "Return the quoted lambda expression." - (cons 'function (list (cons 'lambda args)))) - -(lambda (testing) one two) - -(defun testanon2 () - "return an anoymous function." - (function (lambda (x) x)) - ) -;; Emacs 19 has a lambda macro -(defun testanon2 () - "return an anoymous function." - (lambda (x) x)) -(testanon2) - -(setq func - (testanon2)) -(funcall func 2) - -(defun foo () - (mapcar #'(lambda (x) - (message "%S" x)) - (append '(0) '(a b c d e f)))) -(foo) - -;;==================== -;; downward funarg test - -(defun xxx (func) - (funcall func)) - -(defun yyy () - (xxx (function (lambda () (message "hello"))))) - -(yyy) - -;; eval this: -(def-edebug-spec test nil) -(defun test (func list) - (dolist (el list) - (funcall func el))) - -;; edebug this: -(defun testcall (l) - (test (function (lambda (x) (print x))) ;; set breakpoints in anon. - l)) - -;; test call: -(testcall '(a b c)) - -;; flet test. - -(defun alep-write-history (&rest args) - (message "alep-write-history( %s )\n" - args) - ;; write out header - '(write-region (format ";;Saved on %s\n" (current-time-string)) - nil buffer-file-name nil 'shut-up) - ;; dump all not deleted actions - (flet ((write-solution (sol) - t) - (write-action (action) - (if (a-h-action-deleted action) - ;; nothing to be done - t - (write-region - (format "(alep-new-history-action %S %S %S)\n" - (a-h-action-name action) - (alep-tnowv-string (a-h-action-in-tnowv - action)) - (a-h-action-timestamp action)) - nil buffer-file-name t 'shut-up) - (mapc 'write-solution - (a-h-action-solutions action))))) - (mapc 'write-action - history-list)) - t) -(setq history-list '(1 2 3)) -(alep-write-history) - -;;========================= - - (edebug-trace "my stuff") - -(defun fac (n) - (if (= n 0) (edebug)) -;#6 1 0 =5 - (if (< 0 n) -;#5 = - (* n (fac (1- n))) -;# 5 0 - 1)) -;# 0 - -(fac 5) - - -;;==================== -;; Timing test - how bad is edebug? - -(defun looptest (n) - (let ((i 0)) - (while (< i n) (setq i (1+ i))))) - -(looptest 10000) - -;;==================== -;; eval-depth testing. - -(defun test-depth (i) - (test-depth (1+ i))) - -;; Without edebug i reaches 193, failing on eval depth -;; With edebug, i reaches about 57. Better safe than sorry. -(setq max-lisp-eval-depth 200) -(test-depth 0) - -;;==================== -;; specpdl-size testing. -(defun test-depth2 (i max) - (let ((test max-specpdl-size) - (max-lisp-eval-depth (+ 2 max-lisp-eval-depth)) - ) - (test-depth2 (1+ i) max-specpdl-size))) - -(let ((max-lisp-eval-depth 300) - (max-specpdl-size 3)) - (test-depth2 0 max-specpdl-size)) - -;;==================== -;; Buffer testing. - -(defun zprint-region-1 (start end switches) - (let ((name (concat (buffer-name) "")) - (width tab-width)) - (save-excursion - (message "Spooling...") - (let ((oldbuf (current-buffer))) - (set-buffer (get-buffer-create " *spool temp*")) - (widen) - (erase-buffer) - (insert-buffer-substring oldbuf start end) - (setq tab-width width) - (if (/= tab-width 8) - (untabify (point-min) (point-max))) - (setq start (point-min) end (point-max))) - (apply 'call-process-region - (nconc (list start end zpr-command nil nil nil - "-h" name switches))) - (message "Spooling...done") - ) - ) - ) - - - -(defun quick-hanoi (nrings) - (with-output-to-temp-buffer "*hanio*" - (set-buffer "*hanio*") - (princ (format "Solution to %s ring hanoi problem\n\n" nrings)) - (hanoi0 nrings 'pole-1 'pole-2 'pole-3))) - -(defun hanoi0 (n from to work) -;; (edebug-set-window-configuration (edebug-current-window-configuration)) - (if (> n 0) - (progn -;; (save-excursion -;; (set-buffer "*hanio*") -;; (message "Point=%s window-point=%s" (point) -;; (window-point (get-buffer-window "*hanio*"))) -;; (set-window-point (get-buffer-window "*hanio*") (point)) -;; ) - - (hanoi0 (1- n) from work to) - (princ (format "ring %s from %s to %s\n" n from to)) - (hanoi0 (1- n) work to from)))) - -(quick-hanoi 5) - - -;;==================== -;; Error test - -(defun error-generating-function () - (message "try again?") (sit-for 1) - (prog1 - (signal 'bogus '("some error" xyz abc)) - (error "debug-on-error: %s edebug-entered: %s edebug-recursion-depth: %s" - debug-on-error edebug-entered edebug-recursion-depth))) - -;; --><-- point will be left between the two arrows -(setq debug-on-error nil) -(setq edebug-on-signal '(bogus)) - -(testing-function) -(defun testing-function () - (interactive) - (message "YYY") - (error-generating-function) - (message "ZZZ")) - - -(let ((debug-on-error t)) - xyzzyz) - -;;==================== -;; Quitting with unwind-protect - -(defun unwind-test () - (prog1 - (unwind-protect - (unwind-protect - (message "testing") - (message "unwinding1")) - (message "unwinding2") - (sit-for 1) - ) - )) -(unwind-test) - -(defmacro save-buffer-points (&rest body) - (` (let ((buffer-points - (mapcar (function (lambda (buf) - (set-buffer buf) - (cons buf (point)))) - (buffer-list)))) - (unwind-protect - (progn - (,@ body)) - (mapcar (function (lambda (buf-point) - (if (buffer-name (car buf-point)) - (progn - (set-buffer (car buf-point)) - (goto-char (cdr buf-point)))))) - buffer-points))))) - -(defun testing4 () - (with-output-to-temp-buffer "*testing*" - (princ "Line 1\n") - (save-buffer-points - (recursive-edit) - ) - (princ "Line 2\n") - )) - -(testing4) -test! - - -;;==================== -;; edebug-form-specs for Guido Bosch's flavors - -(def-edebug-spec defmethod defun) ; same as defun -(def-edebug-spec defwhopper defun) ; same as defun - -;;====================== -;; Check syntax errors. - -(defun test-too-many-arguments () - (mapcar 'test one two)) - -(mapcar 'not-enough) - -(defun test-not-enough-arguments () - (mapcar 'test)) - -(defun test-bad-function () - (function)) - -(defun test-bad-function () - (function - (bad () ))) - -(defun test-bad-lambda-arguments () - (function (lambda "bad" ))) - -(defun test-bad-defun-arguments "bad" - (function (lambda "bad" ))) - -(defun test-bad-defun-arguments (arg "bad") ;; wrong error - (function (lambda "bad" ))) - -(defun test-bad-defun-arguments (&optional) - (function (lambda "bad" ))) - -(defun test-bad-let-in-lambda () - (function (lambda () - (let ((something one bad)))))) ;; wrong error - -(defun test-bad-interactive () - (interactive one bad)) - -(defun test-bad-defvar () - (defvar test-defvar nil [bad])) - -(defun test-bad-let1 () - (let bad)) - -(defun test-bad-let2 () - (let ((something one bad)))) - -(defun test-good-let () - (let ((a b)))) - -(defun test-bad-let3 () - (let (((bad))))) - -(defun test-bad-let4 () - (let ("bad"))) - -(let ((good (list 'one))) good) - -(defun test-bad-setq () - (setq "bad" )) - -(setq good ok - "bad") - -(defun test-bad-cond () - (cond "bad")) - -(cond ()) - -(defun test-bad-cond () - (cond () [] "bad")) - -(defun test-bad-condition-case1 () - (condition-case "bad")) - -(defun test-bad-condition-case2 () - (condition-case err - nil - "bad")) - -(defun test-bad-condition-case3 () - (condition-case err - (error "messages") -;; () - ((error quit) (message "%s" err)))) - - -(def-edebug-spec do - ((&rest &or symbolp - (fence symbolp &optional form form)) - (form body) body)) - -(defun bad-do (list) - -(do ( x - (x list (cdr x)) - (y nil (cons (car x) y)) - (x list (cdr x) bad) - "bad" - ) - ((endp x) y) - )) - -(defun ok () - test - ) - -(defun "bad" () ) -(defun) - -;;========================= - -;; Test printing. - -(defun test-window-buffer-change (arg) - "testing" - (interactive arg) - (save-window-excursion - (set-window-buffer (selected-window) (get-buffer "*scratch*")) - (get-buffer-window (current-buffer)))) -(test-window-buffer-change 'test) - - -(defun test-window-buffer-change () - (selected-window)) - -(test-window-buffer-change 1) - -arg - - -(def-edebug-spec edebug-forms - (&rest edebug-form)) - -(def-edebug-spec edebug-form - (&or (edebug-function-symbolp edebug-forms) - (anonymous-function edebug-forms) - (edebug-macro-symbolp - sexp))) - - -(defun test-mapatoms () ) - -(mapatoms (function (lambda (arg) - (princ - arg) - ))) - - -(test-mapatoms) - -;; Test embedded &rest -(def-edebug-spec symbol-list - ([&rest "a" symbolp] form)) - -(defun test () - (symbol-list a b a (+ c d))) -(test) - -(def-edebug-spec group-alternates-test - (&or ["foo" "bar"] "baz")) - -(group-alternates-test foo bar) -(group-alternates-test baz ) - -;;--------------------- - -(defun test () - (dolist (f (list 1 2)) - (message f))) - -(defun test () - (dolist (el (list 'a 'b 'c)) - (print el))) - - -;; (of-type (type (more type))) - -(def-edebug-spec test-nil - (&or symbolp "nil")) -(test-nil () ) - -(defun test () - ((lambda (arg) arg) two) -) - - -;; Dot notation testing - -(def-edebug-spec test-dot - (symbolp . [&or symbolp (stringp)])) -(test-dot xyz . jk) -(test-dot xyz "jk") - -(def-edebug-spec test-dot - (&or symbolp (test-dot1))) - -(def-edebug-spec test-dot1 - (test-dot2 . test-dot2)) - -(def-edebug-spec test-dot2 - (symbolp)) - -(def-edebug-spec test-dot2 - ([&or test-dot1 nil])) - -(def-edebug-spec test-dot1 - (symbolp)) - - (&or symbolp (test-dot))) - - -(defun test () - (test-dot (a . b))) - -(def-edebug-spec edebug-specs - (symbolp . symbolp)) - -(def-edebug-spec edebug-specs1 - (&or symbolp)) - -(def-edebug-spec edebug-spec - (&or - symbolp)) - - -(def-edebug-spec test-not - (symbolp . [¬ symbolp form])) -(test-not "string") - -;;-------------------------- -;; Loop macro testing - -(defun test () - (loop-var (((var1 (var2 var4) . (var3 var5)) . var1)) - )) - -(loop-var (var1 var2 . var3)) -(loop-var (var1 ["bad"] . "bad")) - - ' (var2 var3 . var4)) - -(loop for ((a . b) (c . d)) - of-type ((float . float) (integer. integer)) - ) - -(defun test () - (loop if some-test - collect a-form into var - else minimize x ;; of-type some-type - and append x - end)) - -(defun test () - (loop for x from 1 to 9 - and y = nil then x - collect (list x y))) - -(defun test () - (loop for i from 10 downto 1 by 3 - do (print i))) - - -(defun test () - (loop for item = 1 then (+ item 10) - repeat 5 - collect item)) - -(defun test () - (loop for z upfrom 2 - thereis - (loop for n upfrom 3 below (+ z 2) ;; + was log - thereis - (loop for x below z - thereis - (loop for y below z - thereis (= (+ (* x n) ;; * was expt - (* y n)) - (* z n))))))) - -(defun test () - (loop for name in '(fred sue alice joe june) - as age in '(22 26 19 20 10) - append (list name age) into name-and-age-list - count name into name-count - sum age into total-age - finally - (return (values (round* total-age name-count) - name-and-age-list)))) - -(defun test () - (loop for x from 0 to 3 - do (print x) - if (zerop (mod x 2)) - do (princ " a") - and if (zerop (floor* x 2)) - do (princ " b") - end - and do (princ " c"))) - - -(defun test () - (loop initially do (message x) - do (dispatch-event event))) - -(defun test () - (loop initially do (popup-menu menu) ;; do is an error here. - with event = (allocate-event) - do (dispatch-event event))) - -(defun popup-menu-synchronously (menu) - (loop initially (popup-menu menu) - with event = (allocate-event) - until (button-release-event-p (next-event event)) - do (dispatch-event event) - finally do (deallocate-event event))) - -(defun test () - (loop with list = '(1 2 3 4) - for item in list - sum item into summation - collect (list item))) - -;;---------- - -(defun test-catch (n) - (if (> n 0) - (let* ((test - (catch 'test - (test-catch (1- n))))) - (if test - (do-throw))) - (do-throw))) - -(defun do-throw () - (funcall 'throw 'test 'here)) - -(test-catch 3) - - -;;------------ - -(defun* foo (a &optional b &key c d (e 17))) - -(def-edebug-spec test-vector - ((vector form))) - -(defun test () - - (test-vector [one])) - -[testing one two three] -(testing one two three) - -(def-edebug-spec test - (&optional &or ["something" keywordp] symbolp)) - -(test something :somekey) - -;;---------- - - - -(defun find-faq (filename) - "Hmtar en faq." - (interactive - - (list - (all-faq-a-valid-ftp - (intern-soft - (let ((minibuffer-help-form - (function - (let* ((partial (buffer-string)) - (soft (intern-soft partial all-faq-known-files))) - (if soft - (set soft (append (cdr (symbol-value soft)) - (list (car (symbol-value soft)))))) - (if (and soft (all-faq-a-valid-ftp soft)) - (mapconcat - (function - (lambda (apair) - (car apair))) - (symbol-value soft) - "\n")))))) - (completing-read "What faq? " - all-faq-known-files - (function all-faq-a-valid-ftp) - t "")) - all-faq-known-files))) -) - (find-file filename)) - - -;;=============== - -;; Keyword testing - -(def-edebug-spec test - (&key (bad "one") (good "thing"))) -(defun test-key () - (test :bad one) - (test1 :bad one)) - -(def-edebug-spec test - (("one"))) - - (&rest ["one" "two"])) - -(test (one)) - -(progn (message "one" ) ) -(testet xxx) -(progn (message "one" ) ) - -(let ((a (+ 1 1))) - (1+ a)) - -(mapcar 'test (list 1 2 3)) -(defun test (testing) testing) - -;;================== -;; Test defstruct. - -(defun test () - (defstruct - (test (:constructor construct (args))) - a - (b (+ a c)) - c)) - -;;================ -;; advice - -(defun foo (x) - "Add 1 to x." - (1+ x)) - -(require 'advice) - -(defadvice foo (before add2 first activate) - " Add 2 to x" - (setq x (1+ x))) - -(foo 3) diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/edebug.el --- a/lisp/edebug/edebug.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4604 +0,0 @@ -;;; edebug.el --- a source-level debugger for Emacs Lisp - -;; Copyright (C) 1988,'89,'90,'91,'92,'93,'94,'95 Free Software Foundation, Inc - -;; Author: Daniel LaLiberte -;; Keywords: lisp, tools, maint - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; LCD Archive Entry: -;; edebug|Daniel LaLiberte|liberte@cs.uiuc.edu -;; |A source level debugger for Emacs Lisp. -;; |$Date: 1997/06/14 20:30:57 $|$Revision: 1.6 $|~/modes/edebug.el| - -;; This minor mode allows programmers to step through Emacs Lisp -;; source code while executing functions. You can also set -;; breakpoints, trace (stopping at each expression), evaluate -;; expressions as if outside Edebug, reevaluate and display a list of -;; expressions, trap errors normally caught by debug, and display a -;; debug style backtrace. - -;;; Installation -;; ============= - -;; Put edebug.el in some directory in your load-path and -;; byte-compile it. Also read the beginning of edebug-epoch.el, -;; cl-specs.el, and edebug-cl-read.el if they apply to you. - -;; Unless you are using Emacs 19 which is already set up to use Edebug, -;; put the following forms in your .emacs file. -;; (define-key emacs-lisp-mode-map "\C-xx" 'edebug-eval-top-level-form) -;; (autoload 'edebug-eval-top-level-form "edebug") - -;; If you wish to change the default edebug global command prefix, change: -;; (setq edebug-global-prefix "\C-xX") - -;; Other options, are described in the manual. - -;; In previous versions of Edebug, users were directed to set -;; `debugger' to `edebug-debug'. This is no longer necessary -;; since Edebug automatically sets it whenever Edebug is active. - -;;; Minimal Instructions -;; ===================== - -;; First evaluate a defun with C-xx, then run the function. Step -;; through the code with SPC, mark breakpoints with b, go until a -;; breakpoint is reached with g, and quit execution with q. Use the -;; "?" command in edebug to describe other commands. See edebug.tex -;; or the Emacs 19 Lisp Reference Manual for more instructions. - -;; Send me your enhancements, ideas, bugs, or fixes. -;; For bugs, you can call edebug-submit-bug-report if you have reporter.el. -;; There is an edebug mailing list if you want to keep up -;; with the latest developments. Requests to: edebug-request@cs.uiuc.edu - -;; Daniel LaLiberte 217-398-4114 -;; University of Illinois, Urbana-Champaign -;; Department of Computer Science -;; 1304 W Springfield -;; Urbana, IL 61801 - -;; uiucdcs!liberte -;; liberte@cs.uiuc.edu - -;; For the early revision history, see edebug-history. - -;;; Code: - -(defconst edebug-version - (let ((raw-version "$Revision: 1.6 $")) - (substring raw-version (string-match "[0-9.]*" raw-version) - (match-end 0)))) - -(require 'backquote) - -;; Emacs 18 doesn't have defalias. -(eval-and-compile - (or (fboundp 'defalias) (fset 'defalias 'fset))) - - -;;; Bug reporting - -(defconst edebug-maintainer-address "liberte@cs.uiuc.edu") - -(defun edebug-submit-bug-report () - "Submit, via mail, a bug report on edebug." - (interactive) - (require 'reporter) - (and (y-or-n-p "Do you really want to submit a report on edebug? ") - (reporter-submit-bug-report - edebug-maintainer-address - (concat "edebug.el " edebug-version) - (list 'edebug-setup-hook - 'edebug-all-defs - 'edebug-all-forms - 'edebug-eval-macro-args - 'edebug-stop-before-symbols - 'edebug-save-windows - 'edebug-save-displayed-buffer-points - 'edebug-initial-mode - 'edebug-trace - 'edebug-test-coverage - 'edebug-continue-kbd-macro - 'edebug-print-length - 'edebug-print-level - 'edebug-print-circle - )))) - -;;; Options - -(defgroup edebug nil - "A source-level debugger for Emacs Lisp" - :group 'lisp) - - -(defvar edebug-setup-hook nil - "*Functions to call before edebug is used. -Each time it is set to a new value, Edebug will call those functions -once and then `edebug-setup-hook' is reset to nil. You could use this -to load up Edebug specifications associated with a package you are -using but only when you also use Edebug.") - -(defcustom edebug-all-defs nil - "*If non-nil, evaluation of any defining forms will instrument for Edebug. -This applies to `eval-defun', `eval-region', `eval-buffer', and -`eval-current-buffer'. `eval-region' is also called by -`eval-last-sexp', and `eval-print-last-sexp'. - -You can use the command `edebug-all-defs' to toggle the value of this -variable. You may wish to make it local to each buffer with -\(make-local-variable 'edebug-all-defs) in your -`emacs-lisp-mode-hook'." - :type 'boolean - :group 'edebug) - -(defcustom edebug-all-forms nil - "*Non-nil evaluation of all forms will instrument for Edebug. -This doesn't apply to loading or evaluations in the minibuffer. -Use the command `edebug-all-forms' to toggle the value of this option." - :type 'boolean - :group 'edebug) - -(defcustom edebug-eval-macro-args nil - "*Non-nil means all macro call arguments may be evaluated. -If this variable is nil, the default, Edebug will *not* wrap -macro call arguments as if they will be evaluated. -For each macro, a `edebug-form-spec' overrides this option. -So to specify exceptions for macros that have some arguments evaluated -and some not, you should specify an `edebug-form-spec'. - -This option is going away soon." - :type 'boolean - :group 'edebug) - -(defcustom edebug-stop-before-symbols nil - "*Non-nil causes Edebug to stop before symbols as well as after. -In any case, a breakpoint or interrupt may stop before a symbol. - -This option is going away soon." - :type 'boolean - :group 'edebug) - -(defcustom edebug-save-windows t - "*If non-nil, Edebug saves and restores the window configuration. -That takes some time, so if your program does not care what happens to -the window configurations, it is better to set this variable to nil. - -If the value is a list, only the listed windows are saved and -restored. - -`edebug-toggle-save-windows' may be used to change this variable." - :type '(choice boolean (repeat string)) - :group 'edebug) - -(defcustom edebug-save-displayed-buffer-points nil - "*If non-nil, save and restore point in all displayed buffers. - -Saving and restoring point in other buffers is necessary if you are -debugging code that changes the point of a buffer which is displayed -in a non-selected window. If Edebug or the user then selects the -window, the buffer's point will be changed to the window's point. - -Saving and restoring point in all buffers is expensive, since it -requires selecting each window twice, so enable this only if you need -it." - :type 'boolean - :group 'edebug) - -(defcustom edebug-initial-mode 'step - "*Initial execution mode for Edebug, if non-nil. If this variable -is non-@code{nil}, it specifies the initial execution mode for Edebug -when it is first activated. Possible values are step, next, go, -Go-nonstop, trace, Trace-fast, continue, and Continue-fast." - :type '(choice (const step) (const next) (const go) - (const Go-nonstop) (const trace) - (const Trace-fast) (const continue) - (const continue-fast)) - :group 'edebug) - -(defcustom edebug-trace nil - "*Non-nil means display a trace of function entry and exit. -Tracing output is displayed in a buffer named `*edebug-trace*', one -function entry or exit per line, indented by the recursion level. - -You can customize by replacing functions `edebug-print-trace-before' -and `edebug-print-trace-after'." - :type 'boolean - :group 'edebug) - -(defcustom edebug-test-coverage nil - "*If non-nil, Edebug tests coverage of all expressions debugged. -This is done by comparing the result of each expression -with the previous result. Coverage is considered OK if two different -results are found. - -Use `edebug-display-freq-count' to display the frequency count and -coverage information for a definition." - :type 'boolean - :group 'edebug) - -(defcustom edebug-continue-kbd-macro nil - "*If non-nil, continue defining or executing any keyboard macro. -Use this with caution since it is not debugged." - :type 'boolean - :group 'edebug) - - -(defcustom edebug-print-length 50 - "*Default value of `print-length' to use while printing results in Edebug." - :type 'integer - :group 'edebug) -(defcustom edebug-print-level 50 - "*Default value of `print-level' to use while printing results in Edebug." - :type 'integer - :group 'edebug) -(defcustom edebug-print-circle t - "*Default value of `print-circle' to use while printing results in Edebug." - :type 'boolean - :group 'edebug) - -(defcustom edebug-unwrap-results nil - "*Non-nil if Edebug should unwrap results of expressions. -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." - :type 'boolean - :group 'edebug) - -(defcustom edebug-on-error t - "*Value bound to `debug-on-error' while Edebug is active. - -If `debug-on-error' is non-nil, that value is still used. - -If the value is a list of signal names, Edebug will stop when any of -these errors are signaled from Lisp code whether or not the signal is -handled by a `condition-case'. This option is useful for debugging -signals that *are* handled since they would otherwise be missed. -After execution is resumed, the error is signaled again." - :type '(choice boolean (repeat string)) - :group 'edebug) - -(defcustom edebug-on-quit t - "*Value bound to `debug-on-quit' while Edebug is active." - :type 'boolean - :group 'edebug) - -(defcustom edebug-global-break-condition nil - "*If non-nil, an expression to test for at every stop point. -If the result is non-nil, then break. Errors are ignored." - :type 'sexp - :group 'edebug) - -;;; Form spec utilities. - -;;;###autoload -(defmacro def-edebug-spec (symbol spec) - "Set the edebug-form-spec property of SYMBOL according to SPEC. -Both SYMBOL and SPEC are unevaluated. The SPEC can be 0, t, a symbol -\(naming a function), or a list." - (` (put (quote (, symbol)) 'edebug-form-spec (quote (, spec))))) - -(defmacro def-edebug-form-spec (symbol spec-form) - "For compatibility with old version. Use `def-edebug-spec' instead." - (message "Obsolete: use def-edebug-spec instead.") - (def-edebug-spec symbol (eval spec-form))) - -(defun get-edebug-spec (symbol) - ;; Get the spec of symbol resolving all indirection. - (let ((edebug-form-spec (get symbol 'edebug-form-spec)) - indirect) - (while (and (symbolp edebug-form-spec) - (setq indirect (get edebug-form-spec 'edebug-form-spec))) - ;; (edebug-trace "indirection: %s" edebug-form-spec) - (setq edebug-form-spec indirect)) - edebug-form-spec - )) - -;;; Utilities - -;; Define edebug-gensym - from old cl.el -(defvar edebug-gensym-index 0 - "Integer used by `edebug-gensym' to produce new names.") - -(defun edebug-gensym (&optional prefix) - "Generate a fresh uninterned symbol. -There is an optional argument, PREFIX. PREFIX is the -string that begins the new name. Most people take just the default, -except when debugging needs suggest otherwise." - (if (null prefix) - (setq prefix "G")) - (let ((newsymbol nil) - (newname "")) - (while (not newsymbol) - (setq newname (concat prefix (int-to-string edebug-gensym-index))) - (setq edebug-gensym-index (+ edebug-gensym-index 1)) - (if (not (intern-soft newname)) - (setq newsymbol (make-symbol newname)))) - newsymbol)) - -;; Only used by CL-like code. -(defun edebug-keywordp (object) - "Return t if OBJECT is a keyword. -A keyword is a symbol that starts with `:'." - (and (symbolp object) - (= ?: (aref (symbol-name object) 0)))) - -(defun edebug-lambda-list-keywordp (object) - "Return t if OBJECT is a lambda list keyword. -A lambda list keyword is a symbol that starts with `&'." - (and (symbolp object) - (= ?& (aref (symbol-name object) 0)))) - - -(defun edebug-last-sexp () - ;; Return the last sexp before point in current buffer. - ;; Assumes Emacs Lisp syntax is active. - (car - (read-from-string - (buffer-substring - (save-excursion - (forward-sexp -1) - (point)) - (point))))) - -(defun edebug-window-list () - "Return a list of windows, in order of `next-window'." - ;; This doesn't work for epoch. - (let* ((first-window (selected-window)) - (window-list (list first-window)) - (next (next-window first-window))) - (while (not (eq next first-window)) - (setq window-list (cons next window-list)) - (setq next (next-window next))) - (nreverse window-list))) - -(defun edebug-window-live-p (window) - "Return non-nil if WINDOW is visible." - (let* ((first-window (selected-window)) - (next (next-window first-window t))) - (while (not (or (eq next window) - (eq next first-window))) - (setq next (next-window next t))) - (eq next window))) - -;; Not used. -'(defun edebug-two-window-p () - "Return t if there are two windows." - (and (not (one-window-p)) - (eq (selected-window) - (next-window (next-window (selected-window)))))) - -(defsubst edebug-lookup-function (object) - (while (and (symbolp object) (fboundp object)) - (setq object (symbol-function object))) - object) - -(defun edebug-macrop (object) - "Return the macro named by OBJECT, or nil if it is not a macro." - (setq object (edebug-lookup-function object)) - (if (and (listp object) - (eq 'macro (car object)) - (edebug-functionp (cdr object))) - object)) - -(defun edebug-functionp (object) - "Returns the function named by OBJECT, or nil if it is not a function." - (setq object (edebug-lookup-function object)) - (if (or (subrp object) - (compiled-function-p object) ; XEmacs - (and (listp object) - (eq (car object) 'lambda) - (listp (car (cdr object))))) - object)) - -(defun edebug-sort-alist (alist function) - ;; Return the ALIST sorted with comparison function FUNCTION. - ;; This uses 'sort so the sorting is destructive. - (sort alist (function - (lambda (e1 e2) - (funcall function (car e1) (car e2)))))) - -;;(def-edebug-spec edebug-save-restriction t) - -;; Not used. If it is used, def-edebug-spec must be defined before use. -'(defmacro edebug-save-restriction (&rest body) - "Evaluate BODY while saving the current buffers restriction. -BODY may change buffer outside of current restriction, unlike -save-restriction. BODY may change the current buffer, -and the restriction will be restored to the original buffer, -and the current buffer remains current. -Return the result of the last expression in BODY." - (` (let ((edebug:s-r-beg (point-min-marker)) - (edebug:s-r-end (point-max-marker))) - (unwind-protect - (progn (,@ body)) - (save-excursion - (set-buffer (marker-buffer edebug:s-r-beg)) - (narrow-to-region edebug:s-r-beg edebug:s-r-end)))))) - -;;; Display - -(defconst edebug-trace-buffer "*edebug-trace*" - "Name of the buffer to put trace info in.") - -(defun edebug-pop-to-buffer (buffer &optional window) - ;; Like pop-to-buffer, but select window where BUFFER was last shown. - ;; Select WINDOW if it provided and it still exists. Otherwise, - ;; if buffer is currently shown in several windows, choose one. - ;; Otherwise, find a new window, possibly splitting one. - (setq window (if (and (windowp window) (edebug-window-live-p window) - (eq (window-buffer window) buffer)) - window - (if (eq (window-buffer (selected-window)) buffer) - (selected-window) - (edebug-get-buffer-window buffer)))) - (if window - (select-window window) - (if (one-window-p) - (split-window)) - ;; (message "next window: %s" (next-window)) (sit-for 1) - (if (eq (get-buffer-window edebug-trace-buffer) (next-window)) - ;; Don't select trace window - nil - (select-window (next-window)))) - (set-window-buffer (selected-window) buffer) - (set-window-hscroll (selected-window) 0);; should this be?? - ;; Selecting the window does not set the buffer until command loop. - ;;(set-buffer buffer) - ) - - -(defun edebug-get-displayed-buffer-points () - ;; Return a list of buffer point pairs, for all displayed buffers. - (save-excursion - (let* ((first-window (selected-window)) - (next (next-window first-window)) - (buffer-point-list nil) - buffer) - (while (not (eq next first-window)) - (set-buffer (setq buffer (window-buffer next))) - (setq buffer-point-list - (cons (cons buffer (point)) buffer-point-list)) - (setq next (next-window next))) - buffer-point-list))) - - -(defun edebug-set-buffer-points (buffer-points) - ;; Restore the buffer-points created by edebug-get-displayed-buffer-points. - (let ((current-buffer (current-buffer))) - (mapcar (function (lambda (buf-point) - (if (buffer-name (car buf-point)) ; still exists - (progn - (set-buffer (car buf-point)) - (goto-char (cdr buf-point)))))) - buffer-points) - (set-buffer current-buffer))) - -(defun edebug-current-windows (which-windows) - ;; Get either a full window configuration or some window information. - (if (listp which-windows) - (mapcar (function (lambda (window) - (if (edebug-window-live-p window) - (list window - (window-buffer window) - (window-point window) - (window-start window) - (window-hscroll window))))) - which-windows) - (current-window-configuration))) - -(defun edebug-set-windows (window-info) - ;; Set either a full window configuration or some window information. - (if (listp window-info) - (mapcar (function - (lambda (one-window-info) - (if one-window-info - (apply (function - (lambda (window buffer point start hscroll) - (if (edebug-window-live-p window) - (progn - (set-window-buffer window buffer) - (set-window-point window point) - (set-window-start window start) - (set-window-hscroll window hscroll))))) - one-window-info)))) - window-info) - (set-window-configuration window-info))) - -(defalias 'edebug-get-buffer-window 'get-buffer-window) -(defalias 'edebug-sit-for 'sit-for) -(defalias 'edebug-input-pending-p 'input-pending-p) - - -;;; Redefine read and eval functions -;; read is redefined to maybe instrument forms. -;; eval-defun is redefined to check edebug-all-forms and edebug-all-defs. - -;; Use the Lisp version of eval-region. -(require 'eval-reg "eval-reg") - -;; Save the original read function -(or (fboundp 'edebug-original-read) - (defalias 'edebug-original-read (symbol-function 'read))) - -(defun edebug-read (&optional stream) - "Read one Lisp expression as text from STREAM, return as Lisp object. -If STREAM is nil, use the value of `standard-input' (which see). -STREAM or the value of `standard-input' may be: - a buffer (read from point and advance it) - a marker (read from where it points and advance it) - a function (call it with no arguments for each character, - call it with a char as argument to push a char back) - a string (takes text from string, starting at the beginning) - t (read text line using minibuffer and use it). - -This version, from Edebug, maybe instruments the expression. But the -STREAM must be the current buffer to do so. Whether it instruments is -also dependent on the values of `edebug-all-defs' and -`edebug-all-forms'." - (or stream (setq stream standard-input)) - (if (eq stream (current-buffer)) - (edebug-read-and-maybe-wrap-form) - (edebug-original-read stream))) - -(or (fboundp 'edebug-original-eval-defun) - (defalias 'edebug-original-eval-defun (symbol-function 'eval-defun))) - -;; We should somehow arrange to be able to do this -;; without actually replacing the eval-defun command. -(defun edebug-eval-defun (edebug-it) - "Evaluate the top-level form containing point, or after point. - -This version, from Edebug, has the following differences: With a -prefix argument instrument the code for Edebug. If `edebug-all-defs' is -non-nil, then the code is instrumented *unless* there is a prefix -argument. If instrumenting, it prints: `Edebug: FUNCTIONNAME'. -Otherwise, it prints in the minibuffer." - (interactive "P") - (let* ((edebugging (not (eq (not edebug-it) (not edebug-all-defs)))) - (edebug-result) - (form - (let ((edebug-all-forms edebugging) - (edebug-all-defs (eq edebug-all-defs (not edebug-it)))) - (edebug-read-top-level-form)))) - (if (and (eq (car form) 'defvar) - (cdr-safe (cdr-safe form))) - (setq form (cons 'defconst (cdr form)))) - (setq edebug-result (eval form)) - (if (not edebugging) - (princ edebug-result) - edebug-result))) - - -;;;###autoload -(defalias 'edebug-defun 'edebug-eval-top-level-form) - -;;;###autoload -(defun edebug-eval-top-level-form () - "Evaluate a top level form, such as a defun or defmacro. -This is like `eval-defun', but the code is always instrumented for Edebug. -Print its name in the minibuffer and leave point where it is, -or if an error occurs, leave point after it with mark at the original point." - (interactive) - (eval - ;; Bind edebug-all-forms only while reading, not while evalling - ;; but this causes problems while edebugging edebug. - (let ((edebug-all-forms t) - (edebug-all-defs t)) - (edebug-read-top-level-form)))) - - -(defun edebug-read-top-level-form () - (let ((starting-point (point))) - (end-of-defun) - (beginning-of-defun) - (prog1 - (edebug-read-and-maybe-wrap-form) - ;; Recover point, but only if no error occurred. - (goto-char starting-point)))) - - -;; Compatibility with old versions. -(defalias 'edebug-all-defuns 'edebug-all-defs) - -(defun edebug-all-defs () - "Toggle edebugging of all definitions." - (interactive) - (setq edebug-all-defs (not edebug-all-defs)) - (message "Edebugging all definitions is %s." - (if edebug-all-defs "on" "off"))) - - -(defun edebug-all-forms () - "Toggle edebugging of all forms." - (interactive) - (setq edebug-all-forms (not edebug-all-forms)) - (message "Edebugging all forms is %s." - (if edebug-all-forms "on" "off"))) - - -(defun edebug-install-read-eval-functions () - (interactive) - ;; Don't install if already installed. - (if (eq (symbol-function 'read) 'edebug-read) nil - (elisp-eval-region-install) - (defalias 'read 'edebug-read) - (defalias 'eval-defun 'edebug-eval-defun))) - -(defun edebug-uninstall-read-eval-functions () - (interactive) - (elisp-eval-region-uninstall) - (defalias 'read (symbol-function 'edebug-original-read)) - (defalias 'eval-defun (symbol-function 'edebug-original-eval-defun))) - - -;;; Edebug internal data - -;; The internal data that is needed for edebugging is kept in the -;; buffer-local variable `edebug-form-data'. - -;; XEmacs change? -(defconst edebug-form-data nil) -(make-variable-buffer-local 'edebug-form-data) - -;; A list of entries associating symbols with buffer regions. -;; This is an automatic buffer local variable. Each entry looks like: -;; @code{(@var{symbol} @var{begin-marker} @var{end-marker}). The markers -;; are at the beginning and end of an entry level form and @var{symbol} is -;; a symbol that holds all edebug related information for the form on its -;; property list. - -;; In the future, the symbol will be irrelevant and edebug data will -;; be stored in the definitions themselves rather than in the property -;; list of a symbol. - -(defun edebug-make-form-data-entry (symbol begin end) - (list symbol begin end)) - -(defsubst edebug-form-data-name (entry) - (car entry)) - -(defsubst edebug-form-data-begin (entry) - (nth 1 entry)) - -(defsubst edebug-form-data-end (entry) - (nth 2 entry)) - -(defsubst edebug-set-form-data-entry (entry name begin end) - (setcar entry name);; in case name is changed - (set-marker (nth 1 entry) begin) - (set-marker (nth 2 entry) end)) - -(defun edebug-get-form-data-entry (pnt &optional end-point) - ;; Find the edebug form data entry which is closest to PNT. - ;; If END-POINT is supplied, match must be exact. - ;; Return `nil' if none found. - (let ((rest edebug-form-data) - closest-entry - (closest-dist 999999)) ;; need maxint here - (while (and rest (< 0 closest-dist)) - (let* ((entry (car rest)) - (begin (edebug-form-data-begin entry)) - (dist (- pnt begin))) - (setq rest (cdr rest)) - (if (and (<= 0 dist) - (< dist closest-dist) - (or (not end-point) - (= end-point (edebug-form-data-end entry))) - (<= pnt (edebug-form-data-end entry))) - (setq closest-dist dist - closest-entry entry)))) - closest-entry)) - -;; Also need to find all contained entries, -;; and find an entry given a symbol, which should be just assq. - -(defun edebug-form-data-symbol () -;; Return the edebug data symbol of the form where point is in. -;; If point is not inside a edebuggable form, cause error. - (or (edebug-form-data-name (edebug-get-form-data-entry (point))) - (error "Not inside instrumented form"))) - -(defun edebug-make-top-form-data-entry (new-entry) - ;; Make NEW-ENTRY the first element in the `edebug-form-data' list. - (edebug-clear-form-data-entry new-entry) - (setq edebug-form-data (cons new-entry edebug-form-data))) - -(defun edebug-clear-form-data-entry (entry) -;; If non-nil, clear ENTRY out of the form data. -;; Maybe clear the markers and delete the symbol's edebug property? - (if entry - (progn - ;; Instead of this, we could just find all contained forms. - ;; (put (car entry) 'edebug nil) ; - ;; (mapcar 'edebug-clear-form-data-entry ; dangerous - ;; (get (car entry) 'edebug-dependents)) - ;; (set-marker (nth 1 entry) nil) - ;; (set-marker (nth 2 entry) nil) - (setq edebug-form-data (delq entry edebug-form-data))))) - -;;; Parser utilities - -(defun edebug-syntax-error (&rest args) - ;; Signal an invalid-read-syntax with ARGS. - (signal 'invalid-read-syntax args)) - - -(defconst edebug-read-syntax-table - ;; Lookup table for significant characters indicating the class of the - ;; token that follows. This is not a \"real\" syntax table. - (let ((table (make-vector 256 'symbol)) - (i 0)) - (while (< i ?!) - (aset table i 'space) - (setq i (1+ i))) - (aset table ?\( 'lparen) - (aset table ?\) 'rparen) - (aset table ?\' 'quote) - (aset table ?\` 'backquote) - (aset table ?\, 'comma) - (aset table ?\" 'string) - (aset table ?\? 'char) - (aset table ?\[ 'lbracket) - (aset table ?\] 'rbracket) - (aset table ?\. 'dot) - (aset table ?\# 'hash) - ;; We treat numbers as symbols, because of confusion with -, -1, and 1-. - ;; We don't care about any other chars since they won't be seen. - table)) - -(defun edebug-next-token-class () - ;; Move to the next token and return its class. We only care about - ;; lparen, rparen, dot, quote, backquote, comma, string, char, vector, - ;; or symbol. - (edebug-skip-whitespace) - (aref edebug-read-syntax-table (following-char))) - - -(defun edebug-skip-whitespace () - ;; Leave point before the next token, skipping white space and comments. - (skip-chars-forward " \t\r\n\f") - (while (= (following-char) ?\;) - ;; \r is counted as a comment terminator to support selective display. - (skip-chars-forward "^\n\r") ; skip the comment - (skip-chars-forward " \t\r\n\f"))) - - -;; Mostly obsolete reader; still used in one case. - -(defun edebug-read-sexp () - ;; Read one sexp from the current buffer starting at point. - ;; Leave point immediately after it. A sexp can be a list or atom. - ;; An atom is a symbol (or number), character, string, or vector. - ;; This works for reading anything legitimate, but it - ;; is gummed up by parser inconsistencies (bugs?) - (let ((class (edebug-next-token-class))) - (cond - ;; read goes one too far if a (possibly quoted) string or symbol - ;; is immediately followed by non-whitespace. - ((eq class 'symbol) (prog1 - (edebug-original-read (current-buffer)) - (if (not (eq (aref edebug-read-syntax-table - (preceding-char)) 'symbol)) - (forward-char -1)))) - ((eq class 'string) (prog1 - (edebug-original-read (current-buffer)) - (if (/= (preceding-char) ?\") - (forward-char -1)))) - ((eq class 'quote) (forward-char 1) - (list 'quote (edebug-read-sexp))) - ((eq class 'backquote) - (list '\` (edebug-read-sexp))) - ((eq class 'comma) - (list '\, (edebug-read-sexp))) - (t ; anything else, just read it. - (edebug-original-read (current-buffer)))))) - -;;; Offsets for reader - -;; Define a structure to represent offset positions of expressions. -;; Each offset structure looks like: (before . after) for constituents, -;; or for structures that have elements: (before . after) -;; where the are the offset structures for subexpressions -;; including the head of a list. -(defconst edebug-offsets nil) - -;; Stack of offset structures in reverse order of the nesting. -;; This is used to get back to previous levels. -(defconst edebug-offsets-stack nil) -(defconst edebug-current-offset nil) ; Top of the stack, for convenience. - -;; We must store whether we just read a list with a dotted form that -;; is itself a list. This structure will be condensed, so the offsets -;; must also be condensed. -(defconst edebug-read-dotted-list nil) - -(defsubst edebug-initialize-offsets () - ;; Reinitialize offset recording. - (setq edebug-current-offset nil)) - -(defun edebug-store-before-offset (point) - ;; Add a new offset pair with POINT as the before offset. - (let ((new-offset (list point))) - (if edebug-current-offset - (setcdr edebug-current-offset - (cons new-offset (cdr edebug-current-offset))) - ;; Otherwise, we are at the top level, so initialize. - (setq edebug-offsets new-offset - edebug-offsets-stack nil - edebug-read-dotted-list nil)) - ;; Cons the new offset to the front of the stack. - (setq edebug-offsets-stack (cons new-offset edebug-offsets-stack) - edebug-current-offset new-offset) - )) - -(defun edebug-store-after-offset (point) - ;; Finalize the current offset struct by reversing it and - ;; store POINT as the after offset. - (if (not edebug-read-dotted-list) - ;; Just reverse the offsets of all subexpressions. - (setcdr edebug-current-offset (nreverse (cdr edebug-current-offset))) - - ;; We just read a list after a dot, which will be abbreviated out. - (setq edebug-read-dotted-list nil) - ;; Drop the corresponding offset pair. - ;; That is, nconc the reverse of the rest of the offsets - ;; with the cdr of last offset. - (setcdr edebug-current-offset - (nconc (nreverse (cdr (cdr edebug-current-offset))) - (cdr (car (cdr edebug-current-offset)))))) - - ;; Now append the point using nconc. - (setq edebug-current-offset (nconc edebug-current-offset point)) - ;; Pop the stack. - (setq edebug-offsets-stack (cdr edebug-offsets-stack) - edebug-current-offset (car edebug-offsets-stack))) - -(defun edebug-ignore-offset () - ;; Ignore the last created offset pair. - (setcdr edebug-current-offset (cdr (cdr edebug-current-offset)))) - -(def-edebug-spec edebug-storing-offsets (form body)) -(put 'edebug-storing-offsets 'lisp-indent-hook 1) - -(defmacro edebug-storing-offsets (point &rest body) - (` (unwind-protect - (progn - (edebug-store-before-offset (, point)) - (,@ body)) - (edebug-store-after-offset (point))))) - - -;;; Reader for Emacs Lisp. - -;; Uses edebug-next-token-class (and edebug-skip-whitespace) above. - -(defconst edebug-read-alist - '((symbol . edebug-read-symbol) - (lparen . edebug-read-list) - (string . edebug-read-string) - (quote . edebug-read-quote) - (backquote . edebug-read-backquote) - (comma . edebug-read-comma) - (lbracket . edebug-read-vector) - (hash . edebug-read-function) - )) - -(defun edebug-read-storing-offsets (stream) - (let ((class (edebug-next-token-class)) - func - edebug-read-dotted-list) ; see edebug-store-after-offset - (edebug-storing-offsets (point) - (if (setq func (assq class edebug-read-alist)) - (funcall (cdr func) stream) - ;; anything else, just read it. - (edebug-original-read stream)) - ))) - -(defun edebug-read-symbol (stream) - (prog1 - (edebug-original-read stream) - ;; loses for escaped chars - (if (not (eq (aref edebug-read-syntax-table - (preceding-char)) 'symbol)) - (forward-char -1)))) - -(defun edebug-read-string (stream) - (prog1 - (edebug-original-read stream) - (if (/= (preceding-char) ?\") - (forward-char -1)))) - -(defun edebug-read-quote (stream) - ;; Turn 'thing into (quote thing) - (forward-char 1) - (list - (edebug-storing-offsets (point) 'quote) - (edebug-read-storing-offsets stream))) - -(defun edebug-read-backquote (stream) - ;; Turn `thing into (\` thing) - (let ((opoint (point))) - (forward-char 1) - ;; Generate the same structure of offsets we would have - ;; if the resulting list appeared verbatim in the input text. - (edebug-storing-offsets opoint - (list - (edebug-storing-offsets opoint '\`) - (edebug-read-storing-offsets stream))))) - -(defvar edebug-read-backquote-new nil - "Non-nil if reading the inside of a new-style backquote with no parens around it. -Value of nil means reading the inside of an old-style backquote construct -which is surrounded by an extra set of parentheses. -This controls how we read comma constructs.") - -(defun edebug-read-comma (stream) - ;; Turn ,thing into (\, thing). Handle ,@ and ,. also. - (let ((opoint (point))) - (forward-char 1) - (let ((symbol '\,)) - (cond ((eq (following-char) ?\.) - (setq symbol '\,\.) - (forward-char 1)) - ((eq (following-char) ?\@) - (setq symbol '\,@) - (forward-char 1))) - ;; Generate the same structure of offsets we would have - ;; if the resulting list appeared verbatim in the input text. - (if edebug-read-backquote-new - (list - (edebug-storing-offsets opoint symbol) - (edebug-read-storing-offsets stream)) - (edebug-storing-offsets opoint symbol))))) - -(defun edebug-read-function (stream) - ;; Turn #'thing into (function thing) - (forward-char 1) - (if (/= ?\' (following-char)) (edebug-syntax-error "Bad char")) - (forward-char 1) - (list - (edebug-storing-offsets (point) - (if (featurep 'cl) 'function* 'function)) - (edebug-read-storing-offsets stream))) - -(defun edebug-read-list (stream) - (forward-char 1) ; skip \( - (prog1 - (let ((elements)) - (while (not (memq (edebug-next-token-class) '(rparen dot))) - (if (eq (edebug-next-token-class) 'backquote) - (let ((edebug-read-backquote-new (not (null elements))) - (opoint (point))) - (if edebug-read-backquote-new - (setq elements (cons (edebug-read-backquote stream) elements)) - (forward-char 1) ; Skip backquote. - ;; Call edebug-storing-offsets here so that we - ;; produce the same offsets we would have had - ;; if the backquote were an ordinary symbol. - (setq elements (cons (edebug-storing-offsets opoint '\`) - elements)))) - (setq elements (cons (edebug-read-storing-offsets stream) elements)))) - (setq elements (nreverse elements)) - (if (eq 'dot (edebug-next-token-class)) - (let (dotted-form) - (forward-char 1) ; skip \. - (setq dotted-form (edebug-read-storing-offsets stream)) - elements (nconc elements dotted-form) - (if (not (eq (edebug-next-token-class) 'rparen)) - (edebug-syntax-error "Expected `)'")) - (setq edebug-read-dotted-list (listp dotted-form)) - )) - elements) - (forward-char 1) ; skip \) - )) - -(defun edebug-read-vector (stream) - (forward-char 1) ; skip \[ - (prog1 - (let ((elements)) - (while (not (eq 'rbracket (edebug-next-token-class))) - (setq elements (cons (edebug-read-storing-offsets stream) elements))) - (apply 'vector (nreverse elements))) - (forward-char 1) ; skip \] - )) - -;;; Cursors for traversal of list and vector elements with offsets. - -(defvar edebug-dotted-spec nil) - -(defun edebug-new-cursor (expressions offsets) - ;; Return a new cursor for EXPRESSIONS with OFFSETS. - (if (vectorp expressions) - (setq expressions (append expressions nil))) - (cons expressions offsets)) - -(defsubst edebug-set-cursor (cursor expressions offsets) - ;; Set the CURSOR's EXPRESSIONS and OFFSETS to the given. - ;; Return the cursor. - (setcar cursor expressions) - (setcdr cursor offsets) - cursor) - -'(defun edebug-copy-cursor (cursor) - ;; Copy the cursor using the same object and offsets. - (cons (car cursor) (cdr cursor))) - -(defsubst edebug-cursor-expressions (cursor) - (car cursor)) -(defsubst edebug-cursor-offsets (cursor) - (cdr cursor)) - -(defsubst edebug-empty-cursor (cursor) - ;; Return non-nil if CURSOR is empty - meaning no more elements. - (null (car cursor))) - -(defsubst edebug-top-element (cursor) - ;; Return the top element at the cursor. - ;; Assumes not empty. - (car (car cursor))) - -(defun edebug-top-element-required (cursor &rest error) - ;; Check if a dotted form is required. - (if edebug-dotted-spec (edebug-no-match cursor "Dot expected.")) - ;; Check if there is at least one more argument. - (if (edebug-empty-cursor cursor) (apply 'edebug-no-match cursor error)) - ;; Return that top element. - (edebug-top-element cursor)) - -(defsubst edebug-top-offset (cursor) - ;; Return the top offset pair corresponding to the top element. - (car (cdr cursor))) - -(defun edebug-move-cursor (cursor) - ;; Advance and return the cursor to the next element and offset. - ;; throw no-match if empty before moving. - ;; This is a violation of the cursor encapsulation, but - ;; there is plenty of that going on while matching. - ;; The following test should always fail. - (if (edebug-empty-cursor cursor) - (edebug-no-match cursor "Not enough arguments.")) - (setcar cursor (cdr (car cursor))) - (setcdr cursor (cdr (cdr cursor))) - cursor) - - -(defun edebug-before-offset (cursor) - ;; Return the before offset of the cursor. - ;; If there is nothing left in the offsets, - ;; return one less than the offset itself, - ;; which is the after offset for a list. - (let ((offset (edebug-cursor-offsets cursor))) - (if (consp offset) - (car (car offset)) - (1- offset)))) - -(defun edebug-after-offset (cursor) - ;; Return the after offset of the cursor object. - (let ((offset (edebug-top-offset cursor))) - (while (consp offset) - (setq offset (cdr offset))) - offset)) - -;;; The Parser - -;; The top level function for parsing forms is -;; edebug-read-and-maybe-wrap-form; it calls all the rest. It checks the -;; syntax a bit and leaves point at any error it finds, but otherwise -;; should appear to work like eval-defun. - -;; The basic plan is to surround each expression with a call to -;; the edebug debugger together with indexes into a table of positions of -;; all expressions. Thus an expression "exp" becomes: - -;; (edebug-after (edebug-before 1) 2 exp) - -;; When this is evaluated, first point is moved to the beginning of -;; exp at offset 1 of the current function. The expression is -;; evaluated, which may cause more edebug calls, and then point is -;; moved to offset 2 after the end of exp. - -;; The highest level expressions of the function are wrapped in a call to -;; edebug-enter, which supplies the function name and the actual -;; arguments to the function. See functions edebug-enter, edebug-before, -;; and edebug-after for more details. - -;; Dynamically bound vars, left unbound, but globally declared. -;; This is to quiet the byte compiler. - -;; Window data of the highest definition being wrapped. -;; This data is shared by all embedded definitions. -(defvar edebug-top-window-data) - -(defvar edebug-&optional) -(defvar edebug-&rest) -(defvar edebug-gate nil) ;; whether no-match forces an error. - -(defconst edebug-def-name nil) ; name of definition, used by interactive-form -(defconst edebug-old-def-name nil) ; previous name of containing definition. - -(defconst edebug-error-point nil) -(defconst edebug-best-error nil) - - -(defun edebug-read-and-maybe-wrap-form () - ;; Read a form and wrap it with edebug calls, if the conditions are right. - ;; Here we just catch any no-match not caught below and signal an error. - - ;; Run the setup hook. - (let ((temp-hook edebug-setup-hook)) - (setq edebug-setup-hook nil) - (run-hooks 'temp-hook)) - - (let (result - edebug-top-window-data - edebug-def-name;; make sure it is locally nil - ;; I don't like these here!! - edebug-&optional - edebug-&rest - edebug-gate - edebug-best-error - edebug-error-point - no-match - ;; Do this once here instead of several times. - (max-lisp-eval-depth (+ 800 max-lisp-eval-depth)) - (max-specpdl-size (+ 2000 max-specpdl-size))) - (setq no-match - (catch 'no-match - (setq result (edebug-read-and-maybe-wrap-form1)) - nil)) - (if no-match - (apply 'edebug-syntax-error no-match)) - result)) - - -(defun edebug-read-and-maybe-wrap-form1 () - (let (spec - def-kind - defining-form-p - def-name - ;; These offset things don't belong here, but to support recursive - ;; calls to edebug-read, they need to be here. - edebug-offsets - edebug-offsets-stack - edebug-current-offset ; reset to nil - ) - (save-excursion - (if (and (eq 'lparen (edebug-next-token-class)) - (eq 'symbol (progn (forward-char 1) (edebug-next-token-class)))) - ;; Find out if this is a defining form from first symbol - (setq def-kind (edebug-original-read (current-buffer)) - spec (and (symbolp def-kind) (get-edebug-spec def-kind)) - defining-form-p (and (listp spec) - (eq '&define (car spec))) - ;; This is incorrect in general!! But OK most of the time. - def-name (if (and defining-form-p - (eq 'name (car (cdr spec))) - (eq 'symbol (edebug-next-token-class))) - (edebug-original-read (current-buffer)))))) -;;;(message "all defs: %s all forms: %s" edebug-all-defs edebug-all-forms) - (cond - (defining-form-p - (if (or edebug-all-defs edebug-all-forms) - ;; If it is a defining form and we are edebugging defs, - ;; then let edebug-list-form start it. - (let ((cursor (edebug-new-cursor - (list (edebug-read-storing-offsets (current-buffer))) - (list edebug-offsets)))) - (car - (edebug-make-form-wrapper - cursor - (edebug-before-offset cursor) - (1- (edebug-after-offset cursor)) - (list (cons (symbol-name def-kind) (cdr spec)))))) - - ;; Not edebugging this form, so reset the symbol's edebug - ;; property to be just a marker at the definition's source code. - ;; This only works for defs with simple names. - (put def-name 'edebug (point-marker)) - ;; Also nil out dependent defs. - '(mapcar (function - (lambda (def) - (put def-name 'edebug nil))) - (get def-name 'edebug-dependents)) - (edebug-read-sexp))) - - ;; If all forms are being edebugged, explicitly wrap it. - (edebug-all-forms - (let ((cursor (edebug-new-cursor - (list (edebug-read-storing-offsets (current-buffer))) - (list edebug-offsets)))) - (edebug-make-form-wrapper - cursor - (edebug-before-offset cursor) - (edebug-after-offset cursor) - nil))) - - ;; Not a defining form, and not edebugging. - (t (edebug-read-sexp))) - )) - - -(defvar edebug-def-args) ; args of defining form. -(defvar edebug-def-interactive) ; is it an emacs interactive function? -(defvar edebug-inside-func) ;; whether code is inside function context. -;; Currently def-form sets this to nil; def-body sets it to t. - -(defun edebug-interactive-p-name () - ;; Return a unique symbol for the variable used to store the - ;; status of interactive-p for this function. - (intern (format "edebug-%s-interactive-p" edebug-def-name))) - - -(defun edebug-wrap-def-body (forms) - "Wrap the FORMS of a definition body." - (if edebug-def-interactive - (` (let (((, (edebug-interactive-p-name)) - (interactive-p))) - (, (edebug-make-enter-wrapper forms)))) - (edebug-make-enter-wrapper forms))) - - -(defun edebug-make-enter-wrapper (forms) - ;; Generate the enter wrapper for some forms of a definition. - ;; This is not to be used for the body of other forms, e.g. `while', - ;; since it wraps the list of forms with a call to `edebug-enter'. - ;; Uses the dynamically bound vars edebug-def-name and edebug-def-args. - ;; Do this after parsing since that may find a name. - (setq edebug-def-name - (or edebug-def-name edebug-old-def-name (edebug-gensym "edebug-anon"))) - (` (edebug-enter - (quote (, edebug-def-name)) - (, (if edebug-inside-func - (` (list (,@ - ;; Doesn't work with more than one def-body!! - ;; But the list will just be reversed. - (nreverse edebug-def-args)))) - 'nil)) - (function (lambda () (,@ forms))) - ))) - - -(defvar edebug-form-begin-marker) ; the mark for def being instrumented - -(defvar edebug-offset-index) ; the next available offset index. -(defvar edebug-offset-list) ; the list of offset positions. - -(defun edebug-inc-offset (offset) - ;; modifies edebug-offset-index and edebug-offset-list - ;; accesses edebug-func-marc and buffer point - (prog1 - edebug-offset-index - (setq edebug-offset-list (cons (- offset edebug-form-begin-marker) - edebug-offset-list) - edebug-offset-index (1+ edebug-offset-index)))) - - -(defun edebug-make-before-and-after-form (before-index form after-index) - ;; Return the edebug form for the current function at offset BEFORE-INDEX - ;; given FORM. Looks like: - ;; (edebug-after (edebug-before BEFORE-INDEX) AFTER-INDEX FORM) - ;; Also increment the offset index for subsequent use. - ;; if (not edebug-stop-before-symbols) and form is a symbol, - ;; then don't call edebug-before. - (list 'edebug-after - (list 'edebug-before before-index) - after-index form)) - -(defun edebug-make-after-form (form after-index) - ;; Like edebug-make-before-and-after-form, but only after. - (list 'edebug-after 0 after-index form)) - - -(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)) - (let ((forms (nthcdr 2 (nth 1 (nth 3 sexp))))) - (if (> (length forms) 1) - (cons 'progn forms) ;; could return (values forms) instead. - (car forms)))) - (t sexp);; otherwise it is not wrapped, so just return it. - ) - sexp)) - -(defun edebug-unwrap* (sexp) - "Return the sexp recursively unwrapped." - (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) - new-sexp))) - - -(defun edebug-defining-form (cursor form-begin form-end speclist) - ;; Process the defining form, starting outside the form. - ;; The speclist is a generated list spec that looks like: - ;; (("def-symbol" defining-form-spec-sans-&define)) - ;; Skip the first offset. - (edebug-set-cursor cursor (edebug-cursor-expressions cursor) - (cdr (edebug-cursor-offsets cursor))) - (edebug-make-form-wrapper - cursor - form-begin (1- form-end) - speclist)) - -(defun edebug-make-form-wrapper (cursor form-begin form-end - &optional speclist) - ;; Wrap a form, usually a defining form, but any evaluated one. - ;; If speclist is non-nil, this is being called by edebug-defining-form. - ;; Otherwise it is being called from edebug-read-and-maybe-wrap-form1. - ;; This is a hack, but I havent figured out a simpler way yet. - (let* ((form-data-entry (edebug-get-form-data-entry form-begin form-end)) - ;; Set this marker before parsing. - (edebug-form-begin-marker - (if form-data-entry - (edebug-form-data-begin form-data-entry) - ;; Buffer must be current-buffer for this to work: - (set-marker (make-marker) form-begin)))) - - (let (edebug-offset-list - (edebug-offset-index 0) - result - ;; For definitions. - ;; (edebug-containing-def-name edebug-def-name) - ;; Get name from form-data, if any. - (edebug-old-def-name (edebug-form-data-name form-data-entry)) - edebug-def-name - edebug-def-args - edebug-def-interactive - edebug-inside-func;; whether wrapped code executes inside a function. - ) - - (setq result - (if speclist - (edebug-match cursor speclist) - - ;; else wrap as an enter-form. - (edebug-make-enter-wrapper (list (edebug-form cursor))))) - - ;; Set the name here if it was not set by edebug-make-enter-wrapper. - (setq edebug-def-name - (or edebug-def-name edebug-old-def-name (edebug-gensym "edebug-anon"))) - - ;; Add this def as a dependent of containing def. Buggy. - '(if (and edebug-containing-def-name - (not (get edebug-containing-def-name 'edebug-dependents))) - (put edebug-containing-def-name 'edebug-dependents - (cons edebug-def-name - (get edebug-containing-def-name - 'edebug-dependents)))) - - ;; Create a form-data-entry or modify existing entry's markers. - ;; In the latter case, pointers to the entry remain eq. - (if (not form-data-entry) - (setq form-data-entry - (edebug-make-form-data-entry - edebug-def-name - edebug-form-begin-marker - ;; Buffer must be current-buffer. - (set-marker (make-marker) form-end) - )) - (edebug-set-form-data-entry - form-data-entry edebug-def-name ;; in case name is changed - form-begin form-end)) - - ;; (message "defining: %s" edebug-def-name) (sit-for 2) - (edebug-make-top-form-data-entry form-data-entry) - (message "Edebug: %s" edebug-def-name) - ;;(debug edebug-def-name) - - ;; Destructively reverse edebug-offset-list and make vector from it. - (setq edebug-offset-list (vconcat (nreverse edebug-offset-list))) - - ;; Side effects on the property list of edebug-def-name. - (edebug-clear-frequency-count edebug-def-name) - (edebug-clear-coverage edebug-def-name) - - ;; Set up the initial window data. - (if (not edebug-top-window-data) ;; if not already set, do it now. - (let ((window ;; Find the best window for this buffer. - (or (get-buffer-window (current-buffer)) - (selected-window)))) - (setq edebug-top-window-data - (cons window (window-start window))))) - - ;; Store the edebug data in symbol's property list. - (put edebug-def-name 'edebug - ;; A struct or vector would be better here!! - (list edebug-form-begin-marker - nil ; clear breakpoints - edebug-offset-list - edebug-top-window-data - )) - result - ))) - - -(defun edebug-clear-frequency-count (name) - ;; Create initial frequency count vector. - ;; For each stop point, the counter is incremented each time it is visited. - (put name 'edebug-freq-count - (make-vector (length edebug-offset-list) 0))) - - -(defun edebug-clear-coverage (name) - ;; Create initial coverage vector. - ;; Only need one per expression, but it is simpler to use stop points. - (put name 'edebug-coverage - (make-vector (length edebug-offset-list) 'unknown))) - - -(defun edebug-form (cursor) - ;; Return the instrumented form for the following form. - ;; Add the point offsets to the edebug-offset-list for the form. - (let* ((form (edebug-top-element-required cursor "Expected form")) - (offset (edebug-top-offset cursor))) - (prog1 - (cond - ((consp form) - ;; The first offset for a list form is for the list form itself. - (if (eq 'quote (car form)) - form - (let* ((head (car form)) - (spec (and (symbolp head) (get-edebug-spec head))) - (new-cursor (edebug-new-cursor form offset))) - ;; Find out if this is a defining form from first symbol. - ;; An indirect spec would not work here, yet. - (if (and (consp spec) (eq '&define (car spec))) - (edebug-defining-form - new-cursor - (car offset);; before the form - (edebug-after-offset cursor) - (cons (symbol-name head) (cdr spec))) - ;; Wrap a regular form. - (edebug-make-before-and-after-form - (edebug-inc-offset (car offset)) - (edebug-list-form new-cursor) - ;; After processing the list form, the new-cursor is left - ;; with the offset after the form. - (edebug-inc-offset (edebug-cursor-offsets new-cursor)))) - ))) - - ((symbolp form) - (cond - ;; Check for constant symbols that don't get wrapped. - ((or (memq form '(t nil)) - (and (fboundp 'edebug-keywordp) (edebug-keywordp form))) - form) - - ;; This option may go away. - (edebug-stop-before-symbols - (edebug-make-before-and-after-form - (edebug-inc-offset (car offset)) - form - (edebug-inc-offset (cdr offset)) - )) - - (t ;; just a variable - (edebug-make-after-form form (edebug-inc-offset (cdr offset)))))) - - ;; Anything else is self-evaluating. - (t form)) - (edebug-move-cursor cursor)))) - - -(defsubst edebug-forms (cursor) (edebug-match cursor '(&rest form))) -(defsubst edebug-sexps (cursor) (edebug-match cursor '(&rest sexp))) - -(defsubst edebug-list-form-args (head cursor) - ;; Process the arguments of a list form given that head of form is a symbol. - ;; Helper for edebug-list-form - (let ((spec (get-edebug-spec head))) - (cond - (spec - (cond - ((consp spec) - ;; It is a speclist. - (let (edebug-best-error - edebug-error-point);; This may not be needed. - (edebug-match-sublist cursor spec))) - ((eq t spec) (edebug-forms cursor)) - ((eq 0 spec) (edebug-sexps cursor)) - ((symbolp spec) (funcall spec cursor));; Not used by edebug, - ; but leave it in for compatibility. - )) - ;; No edebug-form-spec provided. - ((edebug-macrop head) - (if edebug-eval-macro-args - (edebug-forms cursor) - (edebug-sexps cursor))) - (t ;; Otherwise it is a function call. - (edebug-forms cursor))))) - - -(defun edebug-list-form (cursor) - ;; Return an instrumented form built from the list form. - ;; The after offset will be left in the cursor after processing the form. - (let ((head (edebug-top-element-required cursor "Expected elements")) - ;; Prevent backtracking whenever instrumenting. - (edebug-gate t) - ;; A list form is never optional because it matches anything. - (edebug-&optional nil) - (edebug-&rest nil)) - ;; Skip the first offset. - (edebug-set-cursor cursor (edebug-cursor-expressions cursor) - (cdr (edebug-cursor-offsets cursor))) - (cond - ((null head) nil) ; () is legal. - - ((symbolp head) - (cond - ((null head) - (edebug-syntax-error "nil head")) - ((eq head 'interactive-p) - ;; Special case: replace (interactive-p) with variable - (setq edebug-def-interactive 'check-it) - (edebug-move-cursor cursor) - (edebug-interactive-p-name)) - (t - (cons head (edebug-list-form-args - head (edebug-move-cursor cursor)))))) - - ((consp head) - (if (and (listp head) (eq (car head) ',)) - (edebug-match cursor '(("," def-form) body)) - ;; Process anonymous function and args. - ;; This assumes no anonymous macros. - (edebug-match-specs cursor '(lambda-expr body) 'edebug-match-specs))) - - (t (edebug-syntax-error - "Head of list form must be a symbol or lambda expression."))) - )) - -;;; Matching of specs. - -(defvar edebug-after-dotted-spec nil) - -(defvar edebug-matching-depth 0) ;; initial value -(defconst edebug-max-depth 150) ;; maximum number of matching recursions. - - -;;; Failure to match - -;; This throws to no-match, if there are higher alternatives. -;; Otherwise it signals an error. The place of the error is found -;; with the two before- and after-offset functions. - -(defun edebug-no-match (cursor &rest edebug-args) - ;; Throw a no-match, or signal an error immediately if gate is active. - ;; Remember this point in case we need to report this error. - (setq edebug-error-point (or edebug-error-point - (edebug-before-offset cursor)) - edebug-best-error (or edebug-best-error edebug-args)) - (if (and edebug-gate (not edebug-&optional)) - (progn - (if edebug-error-point - (goto-char edebug-error-point)) - (apply 'edebug-syntax-error edebug-args)) - (funcall 'throw 'no-match edebug-args))) - - -(defun edebug-match (cursor specs) - ;; Top level spec matching function. - ;; Used also at each lower level of specs. - (let (edebug-&optional - edebug-&rest - edebug-best-error - edebug-error-point - (edebug-gate edebug-gate) ;; locally bound to limit effect - ) - (edebug-match-specs cursor specs 'edebug-match-specs))) - - -(defun edebug-match-one-spec (cursor spec) - ;; Match one spec, which is not a keyword &-spec. - (cond - ((symbolp spec) (edebug-match-symbol cursor spec)) - ((vectorp spec) (edebug-match cursor (append spec nil))) - ((stringp spec) (edebug-match-string cursor spec)) - ((listp spec) (edebug-match-list cursor spec)) - )) - - -(defun edebug-match-specs (cursor specs remainder-handler) - ;; Append results of matching the list of specs. - ;; The first spec is handled and the remainder-handler handles the rest. - (let ((edebug-matching-depth - (if (> edebug-matching-depth edebug-max-depth) - (error "too deep - perhaps infinite loop in spec?") - (1+ edebug-matching-depth)))) - (cond - ((null specs) nil) - - ;; Is the spec dotted? - ((atom specs) - (let ((edebug-dotted-spec t));; Containing spec list was dotted. - (edebug-match-specs cursor (list specs) remainder-handler))) - - ;; Is the form dotted? - ((not (listp (edebug-cursor-expressions cursor)));; allow nil - (if (not edebug-dotted-spec) - (edebug-no-match cursor "Dotted spec required.")) - ;; Cancel dotted spec and dotted form. - (let ((edebug-dotted-spec) - (this-form (edebug-cursor-expressions cursor)) - (this-offset (edebug-cursor-offsets cursor))) - ;; Wrap the form in a list, (by changing the cursor??)... - (edebug-set-cursor cursor (list this-form) this-offset) - ;; and process normally, then unwrap the result. - (car (edebug-match-specs cursor specs remainder-handler)))) - - (t;; Process normally. - (let* ((spec (car specs)) - (rest) - (first-char (and (symbolp spec) (aref (symbol-name spec) 0)))) - ;;(message "spec = %s first char = %s" spec first-char) (sit-for 1) - (nconc - (cond - ((eq ?& first-char);; "&" symbols take all following specs. - (funcall (get-edebug-spec spec) cursor (cdr specs))) - ((eq ?: first-char);; ":" symbols take one following spec. - (setq rest (cdr (cdr specs))) - (funcall (get-edebug-spec spec) cursor (car (cdr specs)))) - (t;; Any other normal spec. - (setq rest (cdr specs)) - (edebug-match-one-spec cursor spec))) - (funcall remainder-handler cursor rest remainder-handler))))))) - - -;; Define specs for all the symbol specs with functions used to process them. -;; Perhaps we shouldn't be doing this with edebug-form-specs since the -;; user may want to define macros or functions with the same names. -;; We could use an internal obarray for these primitive specs. - -(mapcar - (function (lambda (pair) - (put (car pair) 'edebug-form-spec (cdr pair)))) - '((&optional . edebug-match-&optional) - (&rest . edebug-match-&rest) - (&or . edebug-match-&or) - (form . edebug-match-form) - (sexp . edebug-match-sexp) - (body . edebug-match-body) - (&define . edebug-match-&define) - (name . edebug-match-name) - (:name . edebug-match-colon-name) - (arg . edebug-match-arg) - (def-body . edebug-match-def-body) - (def-form . edebug-match-def-form) - ;; Less frequently used: - ;; (function . edebug-match-function) - (lambda-expr . edebug-match-lambda-expr) - (¬ . edebug-match-¬) - (&key . edebug-match-&key) - (place . edebug-match-place) - (gate . edebug-match-gate) - ;; (nil . edebug-match-nil) not this one - special case it. - )) - -(defun edebug-match-symbol (cursor symbol) - ;; Match a symbol spec. - (let* ((spec (get-edebug-spec symbol))) - (cond - (spec - (if (consp spec) - ;; It is an indirect spec. - (edebug-match cursor spec) - ;; Otherwise it should be the symbol name of a function. - ;; There could be a bug here - maybe need to do edebug-match bindings. - (funcall spec cursor))) - - ((null symbol) ;; special case this. - (edebug-match-nil cursor)) - - ((fboundp symbol) ; is it a predicate? - (let ((sexp (edebug-top-element-required cursor "Expected" symbol))) - ;; Special case for edebug-`. - (if (and (listp sexp) (eq (car sexp) ',)) - (edebug-match cursor '(("," def-form))) - (if (not (funcall symbol sexp)) - (edebug-no-match cursor symbol "failed")) - (edebug-move-cursor cursor) - (list sexp)))) - (t (error "%s is not a form-spec or function" symbol)) - ))) - - -(defun edebug-match-sexp (cursor) - (list (prog1 (edebug-top-element-required cursor "Expected sexp") - (edebug-move-cursor cursor)))) - -(defun edebug-match-form (cursor) - (list (edebug-form cursor))) - -(defalias 'edebug-match-place 'edebug-match-form) - ;; Currently identical to edebug-match-form. - ;; This is for common lisp setf-style place arguments. - -(defsubst edebug-match-body (cursor) (edebug-forms cursor)) - -(defun edebug-match-&optional (cursor specs) - ;; Keep matching until one spec fails. - (edebug-&optional-wrapper cursor specs 'edebug-&optional-wrapper)) - -(defun edebug-&optional-wrapper (cursor specs remainder-handler) - (let (result - (edebug-&optional specs) - (edebug-gate nil) - (this-form (edebug-cursor-expressions cursor)) - (this-offset (edebug-cursor-offsets cursor))) - (if (null (catch 'no-match - (setq result - (edebug-match-specs cursor specs remainder-handler)) - ;; Returning nil means no no-match was thrown. - nil)) - result - ;; no-match, but don't fail; just reset cursor and return nil. - (edebug-set-cursor cursor this-form this-offset) - nil))) - - -(defun edebug-&rest-wrapper (cursor specs remainder-handler) - (if (null specs) (setq specs edebug-&rest)) - ;; Reuse the &optional handler with this as the remainder handler. - (edebug-&optional-wrapper cursor specs remainder-handler)) - -(defun edebug-match-&rest (cursor specs) - ;; Repeatedly use specs until failure. - (let ((edebug-&rest specs) ;; remember these - edebug-best-error - edebug-error-point) - (edebug-&rest-wrapper cursor specs 'edebug-&rest-wrapper))) - - -(defun edebug-match-&or (cursor specs) - ;; Keep matching until one spec succeeds, and return its results. - ;; If none match, fail. - ;; This needs to be optimized since most specs spend time here. - (let ((original-specs specs) - (this-form (edebug-cursor-expressions cursor)) - (this-offset (edebug-cursor-offsets cursor))) - (catch 'matched - (while specs - (catch 'no-match - (throw 'matched - (let (edebug-gate ;; only while matching each spec - edebug-best-error - edebug-error-point) - ;; Doesn't support e.g. &or symbolp &rest form - (edebug-match-one-spec cursor (car specs))))) - ;; Match failed, so reset and try again. - (setq specs (cdr specs)) - ;; Reset the cursor for the next match. - (edebug-set-cursor cursor this-form this-offset)) - ;; All failed. - (apply 'edebug-no-match cursor "Expected one of" original-specs)) - )) - - -(defun edebug-match-¬ (cursor specs) - ;; If any specs match, then fail - (if (null (catch 'no-match - (let ((edebug-gate nil)) - (save-excursion - (edebug-match-&or cursor specs))) - nil)) - ;; This means something matched, so it is a no match. - (edebug-no-match cursor "Unexpected")) - ;; This means nothing matched, so it is OK. - nil) ;; So, return nothing - - -(def-edebug-spec &key edebug-match-&key) - -(defun edebug-match-&key (cursor specs) - ;; Following specs must look like ( ) ... - ;; where is the name of a keyword, and spec is its spec. - ;; This really doesn't save much over the expanded form and takes time. - (edebug-match-&rest - cursor - (cons '&or - (mapcar (function (lambda (pair) - (vector (format ":%s" (car pair)) - (car (cdr pair))))) - specs)))) - - -(defun edebug-match-gate (cursor) - ;; Simply set the gate to prevent backtracking at this level. - (setq edebug-gate t) - nil) - - -(defun edebug-match-list (cursor specs) - ;; The spec is a list, but what kind of list, and what context? - (if edebug-dotted-spec - ;; After dotted spec but form did not contain dot, - ;; so match list spec elements as if spliced in. - (prog1 - (let ((edebug-dotted-spec)) - (edebug-match-specs cursor specs 'edebug-match-specs)) - ;; If it matched, really clear the dotted-spec flag. - (setq edebug-dotted-spec nil)) - (let ((spec (car specs)) - (form (edebug-top-element-required cursor "Expected" specs))) - (cond - ((eq 'quote spec) - (let ((spec (car (cdr specs)))) - (cond - ((symbolp spec) - ;; Special case: spec quotes a symbol to match. - ;; Change in future. Use "..." instead. - (if (not (eq spec form)) - (edebug-no-match cursor "Expected" spec)) - (edebug-move-cursor cursor) - (setq edebug-gate t) - form) - (t - (error "Bad spec: %s" specs))))) - - ((listp form) - (prog1 - (list (edebug-match-sublist - ;; First offset is for the list form itself. - ;; Treat nil as empty list. - (edebug-new-cursor form (cdr (edebug-top-offset cursor))) - specs)) - (edebug-move-cursor cursor))) - - ((and (eq 'vector spec) (vectorp form)) - ;; Special case: match a vector with the specs. - (let ((result (edebug-match-sublist - (edebug-new-cursor - form (cdr (edebug-top-offset cursor))) - (cdr specs)))) - (edebug-move-cursor cursor) - (list (apply 'vector result)))) - - (t (edebug-no-match cursor "Expected" specs))) - ))) - - -(defun edebug-match-sublist (cursor specs) - ;; Match a sublist of specs. - (let (edebug-&optional - ;;edebug-best-error - ;;edebug-error-point - ) - (prog1 - ;; match with edebug-match-specs so edebug-best-error is not bound. - (edebug-match-specs cursor specs 'edebug-match-specs) - (if (not (edebug-empty-cursor cursor)) - (if edebug-best-error - (apply 'edebug-no-match cursor edebug-best-error) - ;; A failed &rest or &optional spec may leave some args. - (edebug-no-match cursor "Failed matching" specs) - ))))) - - -(defun edebug-match-string (cursor spec) - (let ((sexp (edebug-top-element-required cursor "Expected" spec))) - (if (not (eq (intern spec) sexp)) - (edebug-no-match cursor "Expected" spec) - ;; Since it matched, failure means immediate error, unless &optional. - (setq edebug-gate t) - (edebug-move-cursor cursor) - (list sexp) - ))) - -(defun edebug-match-nil (cursor) - ;; There must be nothing left to match a nil. - (if (not (edebug-empty-cursor cursor)) - (edebug-no-match cursor "Unmatched argument(s)") - nil)) - - -(defun edebug-match-function (cursor) - (error "Use function-form instead of function in edebug spec")) - -(defun edebug-match-&define (cursor specs) - ;; Match a defining form. - ;; Normally, &define is interpreted specially other places. - ;; This should only be called inside of a spec list to match the remainder - ;; of the current list. e.g. ("lambda" &define args def-body) - (edebug-make-form-wrapper - cursor - (edebug-before-offset cursor) - ;; Find the last offset in the list. - (let ((offsets (edebug-cursor-offsets cursor))) - (while (consp offsets) (setq offsets (cdr offsets))) - offsets) - specs)) - -(defun edebug-match-lambda-expr (cursor) - ;; The expression must be a function. - ;; This will match any list form that begins with a symbol - ;; that has an edebug-form-spec beginning with &define. In - ;; practice, only lambda expressions should be used. - ;; I could add a &lambda specification to avoid confusion. - (let* ((sexp (edebug-top-element-required - cursor "Expected lambda expression")) - (offset (edebug-top-offset cursor)) - (head (and (consp sexp) (car sexp))) - (spec (and (symbolp head) (get-edebug-spec head))) - (edebug-inside-func nil)) - ;; Find out if this is a defining form from first symbol. - (if (and (consp spec) (eq '&define (car spec))) - (prog1 - (list - (edebug-defining-form - (edebug-new-cursor sexp offset) - (car offset);; before the sexp - (edebug-after-offset cursor) - (cons (symbol-name head) (cdr spec)))) - (edebug-move-cursor cursor)) - (edebug-no-match cursor "Expected lambda expression") - ))) - - -(defun edebug-match-name (cursor) - ;; Set the edebug-def-name bound in edebug-defining-form. - (let ((name (edebug-top-element-required cursor "Expected name"))) - ;; Maybe strings and numbers could be used. - (if (not (symbolp name)) - (edebug-no-match cursor "Symbol expected for name of definition")) - (setq edebug-def-name - (if edebug-def-name - ;; Construct a new name by appending to previous name. - (intern (format "%s@%s" edebug-def-name name)) - name)) - (edebug-move-cursor cursor) - (list name))) - -(defun edebug-match-colon-name (cursor spec) - ;; Set the edebug-def-name to the spec. - (setq edebug-def-name - (if edebug-def-name - ;; Construct a new name by appending to previous name. - (intern (format "%s@%s" edebug-def-name spec)) - spec)) - nil) - -(defun edebug-match-arg (cursor) - ;; set the def-args bound in edebug-defining-form - (let ((edebug-arg (edebug-top-element-required cursor "Expected arg"))) - (if (or (not (symbolp edebug-arg)) - (edebug-lambda-list-keywordp edebug-arg)) - (edebug-no-match cursor "Bad argument:" edebug-arg)) - (edebug-move-cursor cursor) - (setq edebug-def-args (cons edebug-arg edebug-def-args)) - (list edebug-arg))) - -(defun edebug-match-def-form (cursor) - ;; Like form but the form is wrapped in edebug-enter form. - ;; The form is assumed to be executing outside of the function context. - ;; This is a hack for now, since a def-form might execute inside as well. - ;; Not to be used otherwise. - (let ((edebug-inside-func nil)) - (list (edebug-make-enter-wrapper (list (edebug-form cursor)))))) - -(defun edebug-match-def-body (cursor) - ;; Like body but body is wrapped in edebug-enter form. - ;; The body is assumed to be executing inside of the function context. - ;; Not to be used otherwise. - (let ((edebug-inside-func t)) - (list (edebug-wrap-def-body (edebug-forms cursor))))) - - -;;;; Edebug Form Specs -;;; ========================================================== -;;; See cl-specs.el for common lisp specs. - -;;;;* Spec for def-edebug-spec -;;; Out of date. - -(defun edebug-spec-p (object) - "Return non-nil if OBJECT is a symbol with an edebug-form-spec property." - (and (symbolp object) - (get object 'edebug-form-spec))) - -(def-edebug-spec def-edebug-spec - ;; Top level is different from lower levels. - (&define :name edebug-spec name - &or "nil" edebug-spec-p "t" "0" (&rest edebug-spec))) - -(def-edebug-spec edebug-spec-list - ;; A list must have something in it, or it is nil, a symbolp - ((edebug-spec . [&or nil edebug-spec]))) - -(def-edebug-spec edebug-spec - (&or - (vector &rest edebug-spec) ; matches a vector - ("vector" &rest edebug-spec) ; matches a vector spec - ("quote" symbolp) - edebug-spec-list - stringp - [edebug-lambda-list-keywordp &rest edebug-spec] - ;; [edebug-keywordp gate edebug-spec] ;; need edebug-keywordp for this. - edebug-spec-p ;; Including all the special ones e.g. form. - symbolp;; a predicate - )) - - -;;;* Emacs special forms and some functions. - -;; quote expects only one argument, although it allows any number. -(def-edebug-spec quote sexp) - -;; The standard defining forms. -(def-edebug-spec defconst defvar) -(def-edebug-spec defvar (symbolp &optional form stringp)) - -(def-edebug-spec defun - (&define name lambda-list - [&optional stringp] - [&optional ("interactive" interactive)] - def-body)) -(def-edebug-spec defmacro - (&define name lambda-list def-body)) - -(def-edebug-spec arglist lambda-list) ;; deprecated - use lambda-list. - -(def-edebug-spec lambda-list - (([&rest arg] - [&optional ["&optional" arg &rest arg]] - &optional ["&rest" arg] - ))) - -(def-edebug-spec interactive - (&optional &or stringp def-form)) - -;; A function-form is for an argument that may be a function or a form. -;; This specially recognizes anonymous functions quoted with quote. -(def-edebug-spec function-form - ;; form at the end could also handle "function", - ;; but recognize it specially to avoid wrapping function forms. - (&or ([&or "quote" "function"] &or symbolp lambda-expr) form)) - -;; function expects a symbol or a lambda or macro expression -;; A macro is allowed by Emacs. -(def-edebug-spec function (&or symbolp lambda-expr)) - -;; lambda is a macro in emacs 19. -(def-edebug-spec lambda (&define lambda-list - [&optional stringp] - [&optional ("interactive" interactive)] - def-body)) - -;; A macro expression is a lambda expression with "macro" prepended. -(def-edebug-spec macro (&define "lambda" lambda-list def-body)) - -;; (def-edebug-spec anonymous-form ((&or ["lambda" lambda] ["macro" macro]))) - -;; Standard functions that take function-forms arguments. -(def-edebug-spec mapcar (function-form form)) -(def-edebug-spec mapconcat (function-form form form)) -(def-edebug-spec mapatoms (function-form &optional form)) -(def-edebug-spec apply (function-form &rest form)) -(def-edebug-spec funcall (function-form &rest form)) - -(def-edebug-spec let - ((&rest &or (symbolp &optional form) symbolp) - body)) - -(def-edebug-spec let* let) - -(def-edebug-spec setq (&rest symbolp form)) -(def-edebug-spec setq-default setq) - -(def-edebug-spec cond (&rest (&rest form))) - -(def-edebug-spec condition-case - (symbolp - form - &rest (symbolp body))) - - -(def-edebug-spec \` (backquote-form)) - -;; Supports quotes inside backquotes, -;; but only at the top level inside unquotes. -(def-edebug-spec backquote-form - (&or - ([&or "," ",@"] &or ("quote" backquote-form) form) - (backquote-form &rest backquote-form) - ;; If you use dotted forms in backquotes, replace the previous line - ;; with the following. This takes quite a bit more stack space, however. - ;; (backquote-form . [&or nil backquote-form]) - (vector &rest backquote-form) - sexp)) - -;; Special version of backquote that instruments backquoted forms -;; destined to be evaluated, usually as the result of a -;; macroexpansion. Backquoted code can only have unquotes (, and ,@) -;; in places where list forms are allowed, and predicates. If the -;; backquote is used in a macro, unquoted code that come from -;; arguments must be instrumented, if at all, with def-form not def-body. - -;; We could assume that all forms (not nested in other forms) -;; in arguments of macros should be def-forms, whether or not the macros -;; are defined with edebug-` but this would be expensive. - -;; ,@ might have some problems. - -(defalias 'edebug-\` '\`) ;; same macro as regular backquote. -(def-edebug-spec edebug-\` (def-form)) - -;; Assume immediate quote in unquotes mean backquote at next higher level. -(def-edebug-spec , (&or ("quote" edebug-`) def-form)) -(def-edebug-spec ,@ (&define ;; so (,@ form) is never wrapped. - &or ("quote" edebug-`) def-form)) - -;; New byte compiler. -(def-edebug-spec defsubst defun) -(def-edebug-spec dont-compile t) -(def-edebug-spec eval-when-compile t) -(def-edebug-spec eval-and-compile t) - -(def-edebug-spec save-selected-window t) -(def-edebug-spec save-current-buffer t) -(def-edebug-spec save-match-data t) -(def-edebug-spec with-output-to-string t) -(def-edebug-spec with-current-buffer t) -(def-edebug-spec with-temp-file t) -(def-edebug-spec with-temp-buffer t) - -;; Anything else? - - -;; Some miscellaneous specs for macros in public packages. -;; Send me yours. - -;; advice.el by Hans Chalupsky (hans@cs.buffalo.edu) - -(def-edebug-spec ad-dolist ((symbolp form &optional form) body)) -(def-edebug-spec defadvice - (&define name ;; thing being advised. - (name ;; class is [&or "before" "around" "after" - ;; "activation" "deactivation"] - name ;; name of advice - &rest sexp ;; optional position and flags - ) - [&optional stringp] - [&optional ("interactive" interactive)] - def-body)) - -;;; The debugger itself - -(defvar edebug-active nil) ;; Non-nil when edebug is active - -;;; add minor-mode-alist entry -(or (assq 'edebug-active minor-mode-alist) - (setq minor-mode-alist (cons (list 'edebug-active " *Debugging*") - minor-mode-alist))) - -(defvar edebug-stack nil) -;; Stack of active functions evaluated via edebug. -;; Should be nil at the top level. - -(defvar edebug-stack-depth -1) -;; Index of last edebug-stack item. - -(defvar edebug-offset-indices nil) -;; Stack of offset indices of visited edebug sexps. -;; Should be nil at the top level. -;; Each function adds one cons. Top is modified with setcar. - - -(defvar edebug-entered nil - ;; Non-nil if edebug has already been entered at this recursive edit level. - ;; This should stay nil at the top level. - ) - -;; Should these be options? -(defconst edebug-debugger 'edebug - ;; Name of function to use for debugging when error or quit occurs. - ;; Set this to 'debug if you want to debug edebug. - ) - - -;; Dynamically bound variables, declared globally but left unbound. -(defvar edebug-function) ; the function being executed. change name!! -(defvar edebug-args) ; the arguments of the function -(defvar edebug-data) ; the edebug data for the function -(defvar edebug-value) ; the result of the expression -(defvar edebug-after-index) -(defvar edebug-def-mark) ; the mark for the definition -(defvar edebug-freq-count) ; the count of expression visits. -(defvar edebug-coverage) ; the coverage results of each expression of function. - -(defvar edebug-buffer) ; which buffer the function is in. -(defvar edebug-result) ; the result of the function call returned by body -(defvar edebug-outside-executing-macro) -(defvar edebug-outside-defining-kbd-macro) - -(defvar edebug-execution-mode 'step) ; Current edebug mode set by user. -(defvar edebug-next-execution-mode nil) ; Use once instead of initial mode. - -(defvar edebug-outside-debug-on-error) ; the value of debug-on-error outside -(defvar edebug-outside-debug-on-quit) ; the value of debug-on-quit outside - -(defvar edebug-outside-pre-command-hook) -(defvar edebug-outside-post-command-hook) -(defvar edebug-outside-post-command-idle-hook) - -;; Emacs 19 -(defvar pre-command-hook nil) -(defvar post-command-hook nil) -(defvar post-command-idle-hook nil) - -(defvar cl-lexical-debug) ;; Defined in cl.el - -;;; Handling signals - -(if (not (fboundp 'edebug-original-signal)) - (defalias 'edebug-original-signal (symbol-function 'signal))) -;; We should use advise for this!! - -(defun edebug-signal (edebug-signal-name edebug-signal-data) - "Signal an error. Args are SIGNAL-NAME, and associated DATA. -A signal name is a symbol with an `error-conditions' property -that is a list of condition names. -A handler for any of those names will get to handle this signal. -The symbol `error' should always be one of them. - -DATA should be a list. Its elements are printed as part of the error message. -If the signal is handled, DATA is made available to the handler. -See `condition-case'. - -This is the Edebug replacement for the standard `signal'. It should -only be active while Edebug is. It checks `debug-on-error' to see -whether it should call the debugger. When execution is resumed, the -error is signaled again." - (if (and (listp debug-on-error) (memq edebug-signal-name debug-on-error)) - (edebug 'error (cons edebug-signal-name edebug-signal-data))) - ;; If we reach here without another non-local exit, then send signal again. - ;; i.e. the signal is not continuable, yet. - (edebug-original-signal edebug-signal-name edebug-signal-data)) - - -;;; Entering Edebug - -(defun edebug-enter (edebug-function edebug-args edebug-body) - ;; Entering FUNC. The arguments are ARGS, and the body is BODY. - ;; Setup edebug variables and evaluate BODY. This function is called - ;; when a function evaluated with edebug-eval-top-level-form is entered. - ;; Return the result of BODY. - - ;; Is this the first time we are entering edebug since - ;; lower-level recursive-edit command? - ;; More precisely, this tests whether Edebug is currently active. - (if (not edebug-entered) - (let ((edebug-entered t) - ;; Binding max-lisp-eval-depth here is OK, - ;; but not inside an unwind-protect. - ;; Doing it here also keeps it from growing too large. - (max-lisp-eval-depth (+ 100 max-lisp-eval-depth)) ; too much?? - (max-specpdl-size (+ 200 max-specpdl-size)) - - (debugger edebug-debugger) ; only while edebug is active. - (edebug-outside-debug-on-error debug-on-error) - (edebug-outside-debug-on-quit debug-on-quit) - ;; Binding these may not be the right thing to do. - ;; We want to allow the global values to be changed. - (debug-on-error (or debug-on-error edebug-on-error)) - (debug-on-quit edebug-on-quit) - - ;; Lexical bindings must be uncompiled for this to work. - (cl-lexical-debug t) - - ;; Save the outside value of executing macro. (here??) - (edebug-outside-executing-macro executing-kbd-macro) - (edebug-outside-pre-command-hook pre-command-hook) - (edebug-outside-post-command-hook post-command-hook) - (edebug-outside-post-command-idle-hook post-command-idle-hook)) - (unwind-protect - (let (;; Don't keep reading from an executing kbd macro - ;; within edebug unless edebug-continue-kbd-macro is - ;; non-nil. Again, local binding may not be best. - (executing-kbd-macro - (if edebug-continue-kbd-macro executing-kbd-macro)) - - ;; Disable command hooks. This is essential when - ;; a hook function is instrumented - to avoid infinite loop. - ;; This may be more than we need, however. - (pre-command-hook nil) - (post-command-hook nil) - (post-command-idle-hook nil)) - (setq edebug-execution-mode (or edebug-next-execution-mode - edebug-initial-mode - edebug-execution-mode) - edebug-next-execution-mode nil) - ;; Bind signal to edebug-signal only while Edebug is active. - (fset 'signal 'edebug-signal) - (unwind-protect - (edebug-enter edebug-function edebug-args edebug-body) - (fset 'signal (symbol-function 'edebug-original-signal)))) - ;; Reset global variables in case outside value was changed. - (setq executing-kbd-macro edebug-outside-executing-macro - pre-command-hook edebug-outside-pre-command-hook - post-command-hook edebug-outside-post-command-hook - post-command-idle-hook edebug-outside-post-command-idle-hook - ))) - - (let* ((edebug-data (get edebug-function 'edebug)) - (edebug-def-mark (car edebug-data)) ; mark at def start - (edebug-freq-count (get edebug-function 'edebug-freq-count)) - (edebug-coverage (get edebug-function 'edebug-coverage)) - (edebug-buffer (marker-buffer edebug-def-mark)) - - (edebug-stack (cons edebug-function edebug-stack)) - (edebug-offset-indices (cons 0 edebug-offset-indices)) - ) - (if (get edebug-function 'edebug-on-entry) - (progn - (setq edebug-execution-mode 'step) - (if (eq (get edebug-function 'edebug-on-entry) 'temp) - (put edebug-function 'edebug-on-entry nil)))) - (if edebug-trace - (edebug-enter-trace edebug-body) - (funcall edebug-body)) - ))) - - -(defun edebug-enter-trace (edebug-body) - (let ((edebug-stack-depth (1+ edebug-stack-depth)) - edebug-result) - (edebug-print-trace-before - (format "%s args: %s" edebug-function edebug-args)) - (prog1 (setq edebug-result (funcall edebug-body)) - (edebug-print-trace-after - (format "%s result: %s" edebug-function edebug-result))))) - -(def-edebug-spec edebug-tracing (form body)) - -(defmacro edebug-tracing (msg &rest body) - "Print MSG in *edebug-trace* before and after evaluating BODY. -The result of BODY is also printed." - (` (let ((edebug-stack-depth (1+ edebug-stack-depth)) - edebug-result) - (edebug-print-trace-before (, msg)) - (prog1 (setq edebug-result (progn (,@ body))) - (edebug-print-trace-after - (format "%s result: %s" (, msg) edebug-result)))))) - -(defun edebug-print-trace-before (msg) - "Function called to print trace info before expression evaluation. -MSG is printed after `::::{ '." - (edebug-trace-display - edebug-trace-buffer "%s{ %s" (make-string edebug-stack-depth ?\:) msg)) - -(defun edebug-print-trace-after (msg) - "Function called to print trace info after expression evaluation. -MSG is printed after `::::} '." - (edebug-trace-display - edebug-trace-buffer "%s} %s" (make-string edebug-stack-depth ?\:) msg)) - - - -(defun edebug-slow-before (edebug-before-index) - ;; Debug current function given BEFORE position. - ;; Called from functions compiled with edebug-eval-top-level-form. - ;; Return the before index. - (setcar edebug-offset-indices edebug-before-index) - - ;; Increment frequency count - (aset edebug-freq-count edebug-before-index - (1+ (aref edebug-freq-count edebug-before-index))) - - (if (or (not (memq edebug-execution-mode '(Go-nonstop next))) - (edebug-input-pending-p)) - (edebug-debugger edebug-before-index 'before nil)) - edebug-before-index) - -(defun edebug-fast-before (edebug-before-index) - ;; Do nothing. - ) - -(defun edebug-slow-after (edebug-before-index edebug-after-index edebug-value) - ;; Debug current function given AFTER position and VALUE. - ;; Called from functions compiled with edebug-eval-top-level-form. - ;; Return VALUE. - (setcar edebug-offset-indices edebug-after-index) - - ;; Increment frequency count - (aset edebug-freq-count edebug-after-index - (1+ (aref edebug-freq-count edebug-after-index))) - (if edebug-test-coverage (edebug-update-coverage)) - - (if (and (eq edebug-execution-mode 'Go-nonstop) - (not (edebug-input-pending-p))) - ;; Just return result. - edebug-value - (edebug-debugger edebug-after-index 'after edebug-value) - )) - -(defun edebug-fast-after (edebug-before-index edebug-after-index edebug-value) - ;; Do nothing but return the value. - edebug-value) - -(defun edebug-run-slow () - (defalias 'edebug-before 'edebug-slow-before) - (defalias 'edebug-after 'edebug-slow-after)) - -;; This is not used, yet. -(defun edebug-run-fast () - (defalias 'edebug-before 'edebug-fast-before) - (defalias 'edebug-after 'edebug-fast-after)) - -(edebug-run-slow) - - -(defun edebug-update-coverage () - (let ((old-result (aref edebug-coverage edebug-after-index))) - (cond - ((eq 'ok-coverage old-result)) - ((eq 'unknown old-result) - (aset edebug-coverage edebug-after-index edebug-value)) - ;; Test if a different result. - ((not (eq edebug-value old-result)) - (aset edebug-coverage edebug-after-index 'ok-coverage))))) - - -;; Dynamically declared unbound variables. -(defvar edebug-arg-mode) ; the mode, either before, after, or error -(defvar edebug-breakpoints) -(defvar edebug-break-data) ; break data for current function. -(defvar edebug-break) ; whether a break occurred. -(defvar edebug-global-break) ; whether a global break occurred. -(defvar edebug-break-condition) ; whether the breakpoint is conditional. - -(defvar edebug-break-result nil) -(defvar edebug-global-break-result nil) - - -(defun edebug-debugger (edebug-offset-index edebug-arg-mode edebug-value) - ;; Check breakpoints and pending input. - ;; If edebug display should be updated, call edebug-display. - ;; Return edebug-value. - (let* (;; This needs to be here since breakpoints may be changed. - (edebug-breakpoints (car (cdr edebug-data))) ; list of breakpoints - (edebug-break-data (assq edebug-offset-index edebug-breakpoints)) - (edebug-break-condition (car (cdr edebug-break-data))) - (edebug-global-break - (if edebug-global-break-condition - (condition-case nil - (setq edebug-global-break-result - (eval edebug-global-break-condition)) - (error nil)))) - (edebug-break)) - -;;; (edebug-trace "exp: %s" edebug-value) - ;; Test whether we should break. - (setq edebug-break - (or edebug-global-break - (and edebug-break-data - (or (not edebug-break-condition) - (setq edebug-break-result - (eval edebug-break-condition)))))) - (if (and edebug-break - (nth 2 edebug-break-data)) ; is it temporary? - ;; Delete the breakpoint. - (setcdr edebug-data - (cons (delq edebug-break-data edebug-breakpoints) - (cdr (cdr edebug-data))))) - - ;; Display if mode is not go, continue, or Continue-fast - ;; or break, or input is pending, - (if (or (not (memq edebug-execution-mode '(go continue Continue-fast))) - edebug-break - (edebug-input-pending-p)) - (edebug-display)) ; <--------------- display - - edebug-value - )) - - -;; window-start now stored with each function. -;;(defvar edebug-window-start nil) -;; Remember where each buffers' window starts between edebug calls. -;; This is to avoid spurious recentering. -;; Does this still need to be buffer-local?? -;;(setq-default edebug-window-start nil) -;;(make-variable-buffer-local 'edebug-window-start) - - -;; Dynamically declared unbound vars -(defvar edebug-point) ; the point in edebug buffer -(defvar edebug-outside-buffer) ; the current-buffer outside of edebug -(defvar edebug-outside-point) ; the point outside of edebug -(defvar edebug-outside-mark) ; the mark outside of edebug -(defvar edebug-window-data) ; window and window-start for current function -(defvar edebug-outside-windows) ; outside window configuration -(defvar edebug-eval-buffer) ; for the evaluation list. -(defvar edebug-outside-o-a-p) ; outside overlay-arrow-position -(defvar edebug-outside-o-a-s) ; outside overlay-arrow-string -(defvar edebug-outside-c-i-e-a) ; outside cursor-in-echo-area - -(defvar edebug-eval-list nil) ;; List of expressions to evaluate. - -(defvar edebug-previous-result nil) ;; Last result returned. - -;; Emacs 19 adds an arg to mark and mark-marker. -(defalias 'edebug-mark 'mark) -(defalias 'edebug-mark-marker 'mark-marker) - - -(defun edebug-display () - ;; Setup windows for edebug, determine mode, maybe enter recursive-edit. - ;; Uses local variables of edebug-enter, edebug-before, edebug-after - ;; and edebug-debugger. - (let ((edebug-active t) ; for minor mode alist - edebug-stop ; should we enter recursive-edit - (edebug-point (+ edebug-def-mark - (aref (nth 2 edebug-data) edebug-offset-index))) - edebug-buffer-outside-point ; current point in edebug-buffer - ;; window displaying edebug-buffer - (edebug-window-data (nth 3 edebug-data)) - (edebug-outside-window (selected-window)) - (edebug-outside-buffer (current-buffer)) - (edebug-outside-point (point)) - (edebug-outside-mark (edebug-mark)) - edebug-outside-windows ; window or screen configuration - edebug-buffer-points - - edebug-eval-buffer ; declared here so we can kill it below - (edebug-eval-result-list (and edebug-eval-list - (edebug-eval-result-list))) - edebug-trace-window - edebug-trace-window-start - - (edebug-outside-o-a-p overlay-arrow-position) - (edebug-outside-o-a-s overlay-arrow-string) - (edebug-outside-c-i-e-a cursor-in-echo-area)) - (unwind-protect - (let ((overlay-arrow-position overlay-arrow-position) - (overlay-arrow-string overlay-arrow-string) - (cursor-in-echo-area nil) - ;; any others?? - ) - (if (not (buffer-name edebug-buffer)) - (let ((debug-on-error nil)) - (error "Buffer defining %s not found" edebug-function))) - - (if (eq 'after edebug-arg-mode) - ;; Compute result string now before windows are modified. - (edebug-compute-previous-result edebug-value)) - - (if edebug-save-windows - ;; Save windows now before we modify them. - (setq edebug-outside-windows - (edebug-current-windows edebug-save-windows))) - - (if edebug-save-displayed-buffer-points - (setq edebug-buffer-points (edebug-get-displayed-buffer-points))) - - ;; First move the edebug buffer point to edebug-point - ;; so that window start doesn't get changed when we display it. - ;; I don't know if this is going to help. - ;;(set-buffer edebug-buffer) - ;;(goto-char edebug-point) - - ;; If edebug-buffer is not currently displayed, - ;; first find a window for it. - (edebug-pop-to-buffer edebug-buffer (car edebug-window-data)) - (setcar edebug-window-data (selected-window)) - - ;; Now display eval list, if any. - ;; This is done after the pop to edebug-buffer - ;; so that buffer-window correspondence is correct after quitting. - (edebug-eval-display edebug-eval-result-list) - ;; The evaluation list better not have deleted edebug-window-data. - (select-window (car edebug-window-data)) - (set-buffer edebug-buffer) - - (setq edebug-buffer-outside-point (point)) - (goto-char edebug-point) - - (if (eq 'before edebug-arg-mode) - ;; Check whether positions are up-to-date. - ;; This assumes point is never before symbol. - (if (not (memq (following-char) '(?\( ?\# ?\` ))) - (let ((debug-on-error nil)) - (error "Source has changed - reevaluate definition of %s" - edebug-function) - ))) - - (setcdr edebug-window-data - (edebug-adjust-window (cdr edebug-window-data))) - - ;; Test if there is input, not including keyboard macros. - (if (edebug-input-pending-p) - (progn - (setq edebug-execution-mode 'step - edebug-stop t) - (edebug-stop) - ;; (discard-input) ; is this unfriendly?? - )) - ;; Now display arrow based on mode. - (edebug-overlay-arrow) - - (cond - ((eq 'error edebug-arg-mode) - ;; Display error message - (setq edebug-execution-mode 'step) - (edebug-overlay-arrow) - (beep) - (if (eq 'quit (car edebug-value)) - (message "Quit") - (edebug-report-error edebug-value))) - (edebug-break - (cond - (edebug-global-break - (message "Global Break: %s => %s" - edebug-global-break-condition - edebug-global-break-result)) - (edebug-break-condition - (message "Break: %s => %s" - edebug-break-condition - edebug-break-result)) - ((not (eq edebug-execution-mode 'Continue-fast)) - (message "Break")) - (t))) - - (t (message ""))) - - (if (eq 'after edebug-arg-mode) - (progn - ;; Display result of previous evaluation. - (if (and edebug-break - (not (eq edebug-execution-mode 'Continue-fast))) - (sit-for 1)) ; Show break message. - (edebug-previous-result))) - - (cond - (edebug-break - (cond - ((eq edebug-execution-mode 'continue) (edebug-sit-for 1)) - ((eq edebug-execution-mode 'Continue-fast) (edebug-sit-for 0)) - (t (setq edebug-stop t)))) - ;; not edebug-break - ((eq edebug-execution-mode 'trace) - (edebug-sit-for 1)) ; Force update and pause. - ((eq edebug-execution-mode 'Trace-fast) - (edebug-sit-for 0)) ; Force update and continue. - ) - - (unwind-protect - (if (or edebug-stop - (memq edebug-execution-mode '(step next)) - (eq edebug-arg-mode 'error)) - (progn - ;; (setq edebug-execution-mode 'step) - ;; (edebug-overlay-arrow) ; this doesn't always show up. - (edebug-recursive-edit))) ; <---------- Recursive edit - - ;; Reset the edebug-window-data to whatever it is now. - (let ((window (if (eq (window-buffer) edebug-buffer) - (selected-window) - (edebug-get-buffer-window edebug-buffer)))) - ;; Remember window-start for edebug-buffer, if still displayed. - (if window - (progn - (setcar edebug-window-data window) - (setcdr edebug-window-data (window-start window))))) - - ;; Save trace window point before restoring outside windows. - ;; Could generalize this for other buffers. - (setq edebug-trace-window (get-buffer-window edebug-trace-buffer)) - (if edebug-trace-window - (setq edebug-trace-window-start - (and edebug-trace-window - (window-start edebug-trace-window)))) - - ;; Restore windows before continuing. - (if edebug-save-windows - (progn - (edebug-set-windows edebug-outside-windows) - - ;; Restore displayed buffer points. - ;; Needed even if restoring windows because - ;; window-points are not restored. (should they be??) - (if edebug-save-displayed-buffer-points - (edebug-set-buffer-points edebug-buffer-points)) - - ;; Unrestore trace window's window-point. - (if edebug-trace-window - (set-window-start edebug-trace-window - edebug-trace-window-start)) - - ;; Unrestore edebug-buffer's window-start, if displayed. - (let ((window (car edebug-window-data))) - (if (and window (edebug-window-live-p window) - (eq (window-buffer) edebug-buffer)) - (progn - (set-window-start window (cdr edebug-window-data) - 'no-force) - ;; Unrestore edebug-buffer's window-point. - ;; Needed in addition to setting the buffer point - ;; - otherwise quitting doesn't leave point as is. - ;; But this causes point to not be restored at times. - ;; Also, it may not be a visible window. - ;; (set-window-point window edebug-point) - ))) - - ;; Unrestore edebug-buffer's point. Rerestored below. - ;; (goto-char edebug-point) ;; in edebug-buffer - ) - ;; Since we may be in a save-excursion, in case of quit, - ;; reselect the outside window only. - ;; Only needed if we are not recovering windows?? - (if (edebug-window-live-p edebug-outside-window) - (select-window edebug-outside-window)) - ) ; if edebug-save-windows - - ;; Restore current buffer always, in case application needs it. - (set-buffer edebug-outside-buffer) - ;; Restore point, and mark. - ;; Needed even if restoring windows because - ;; that doesn't restore point and mark in the current buffer. - ;; But don't restore point if edebug-buffer is current buffer. - (if (not (eq edebug-buffer edebug-outside-buffer)) - (goto-char edebug-outside-point)) - (if (marker-buffer (edebug-mark-marker)) - ;; Does zmacs-regions need to be nil while doing set-marker? - (set-marker (edebug-mark-marker) edebug-outside-mark)) - ) ; unwind-protect - ;; None of the following is done if quit or signal occurs. - - ;; Restore edebug-buffer's outside point. - ;; (edebug-trace "restore edebug-buffer point: %s" - ;; edebug-buffer-outside-point) - (let ((current-buffer (current-buffer))) - (set-buffer edebug-buffer) - (goto-char edebug-buffer-outside-point) - (set-buffer current-buffer)) - ;; ... nothing more. - ) - ;; Reset global variables to outside values in case they were changed. - (setq - overlay-arrow-position edebug-outside-o-a-p - overlay-arrow-string edebug-outside-o-a-s - cursor-in-echo-area edebug-outside-c-i-e-a) - ))) - - -(defvar edebug-number-of-recursions 0) -;; Number of recursive edits started by edebug. -;; Should be 0 at the top level. - -(defvar edebug-recursion-depth 0) -;; Value of recursion-depth when edebug was called. - -;; Dynamically declared unbound vars -(defvar edebug-outside-match-data) ; match data outside of edebug -(defvar edebug-backtrace-buffer) ; each recursive edit gets its own -(defvar edebug-inside-windows) -(defvar edebug-interactive-p) - -(defvar edebug-outside-map) -(defvar edebug-outside-standard-output) -(defvar edebug-outside-standard-input) -(defvar edebug-outside-last-command-char) -(defvar edebug-outside-last-command) -(defvar edebug-outside-this-command) -(defvar edebug-outside-last-input-char) - -;; Note: here we have defvars for variables that are -;; built-in in certain versions. -;; Each defvar makes a difference -;; in versions where the variable is *not* built-in. - -;; Emacs 18 -(defvar edebug-outside-unread-command-char) - -;; XEmacs -(defvar edebug-outside-unread-command-event) ;; like unread-command-events -(defvar unread-command-event nil) - -;; Emacs 19. -(defvar edebug-outside-last-command-event) -(defvar edebug-outside-unread-command-events) -(defvar edebug-outside-last-input-event) -(defvar edebug-outside-last-event-frame) -(defvar edebug-outside-last-nonmenu-event) -(defvar edebug-outside-track-mouse) - -;; Disable byte compiler warnings about unread-command-char and -event -;; (maybe works with byte-compile-version 2.22 at least) -(defvar edebug-unread-command-char-warning) -(defvar edebug-unread-command-event-warning) -(eval-when-compile - (setq edebug-unread-command-char-warning - (get 'unread-command-char 'byte-obsolete-variable)) - (put 'unread-command-char 'byte-obsolete-variable nil) - (setq edebug-unread-command-event-warning - (get 'unread-command-event 'byte-obsolete-variable)) - (put 'unread-command-event 'byte-obsolete-variable nil)) - -(defun edebug-recursive-edit () - ;; Start up a recursive edit inside of edebug. - ;; The current buffer is the edebug-buffer, which is put into edebug-mode. - ;; Assume that none of the variables below are buffer-local. - (let ((edebug-buffer-read-only buffer-read-only) - ;; match-data must be done in the outside buffer - (edebug-outside-match-data - (save-excursion ; might be unnecessary now?? - (set-buffer edebug-outside-buffer) ; in case match buffer different - (match-data))) - - ;;(edebug-number-of-recursions (1+ edebug-number-of-recursions)) - (edebug-recursion-depth (recursion-depth)) - edebug-entered ; bind locally to nil - (edebug-interactive-p nil) ; again non-interactive - edebug-backtrace-buffer ; each recursive edit gets its own - ;; The window configuration may be saved and restored - ;; during a recursive-edit - edebug-inside-windows - - (edebug-outside-map (current-local-map)) - - (edebug-outside-standard-output standard-output) - (edebug-outside-standard-input standard-input) - (edebug-outside-defining-kbd-macro defining-kbd-macro) - - (edebug-outside-last-command-char last-command-char) - (edebug-outside-last-command last-command) - (edebug-outside-this-command this-command) - (edebug-outside-last-input-char last-input-char) - - ;; XEmacs: added the boundp checks - (edebug-outside-unread-command-char - (and (boundp 'unread-command-char) unread-command-char)) - - (edebug-outside-last-input-event - (and (boundp 'last-input-event) last-input-event)) - (edebug-outside-last-command-event - (and (boundp 'last-command-event) last-command-event)) - (edebug-outside-unread-command-event - (and (boundp 'unread-command-event) unread-command-event)) - (edebug-outside-unread-command-events - (and (boundp 'unread-command-events) unread-command-events)) - (edebug-outside-last-event-frame - (and (boundp 'last-event-frame) last-event-frame)) - (edebug-outside-last-nonmenu-event - (and (boundp 'last-nonmenu-event) last-nonmenu-event)) - (edebug-outside-track-mouse - (and (boundp 'track-mouse) track-mouse)) - ) - - (unwind-protect - (let ( - ;; Declare global values local but using the same global value. - ;; We could set these to the values for previous edebug call. - (last-command-char last-command-char) - (last-command last-command) - (this-command this-command) - (last-input-char last-input-char) - - ;; Assume no edebug command sets unread-command-char. - (unread-command-char -1) - - ;; More for Emacs 19 - (last-input-event nil) - (last-command-event nil) - (unread-command-event nil);; XEmacs - (unread-command-events nil) - (last-event-frame nil) - (last-nonmenu-event nil) - (track-mouse nil) - - ;; Bind again to outside values. - (debug-on-error edebug-outside-debug-on-error) - (debug-on-quit edebug-outside-debug-on-quit) - - ;; Don't keep defining a kbd macro. - (defining-kbd-macro - (if edebug-continue-kbd-macro defining-kbd-macro)) - - ;; others?? - ) - - (if (fboundp 'zmacs-deactivate-region);; for XEmacs - (zmacs-deactivate-region)) - (if (and (eq edebug-execution-mode 'go) - (not (memq edebug-arg-mode '(after error)))) - (message "Break")) - - (setq buffer-read-only t) - (fset 'signal (symbol-function 'edebug-original-signal)) - - (edebug-mode) - (unwind-protect - (recursive-edit) ; <<<<<<<<<< Recursive edit - - ;; Do the following, even if quit occurs. - (fset 'signal 'edebug-signal) - (if edebug-backtrace-buffer - (kill-buffer edebug-backtrace-buffer)) - ;; Could be an option to keep eval display up. - (if edebug-eval-buffer (kill-buffer edebug-eval-buffer)) - - ;; Remember selected-window after recursive-edit. - ;; (setq edebug-inside-window (selected-window)) - - (store-match-data edebug-outside-match-data) - - ;; Recursive edit may have changed buffers, - ;; so set it back before exiting let. - (if (buffer-name edebug-buffer) ; if it still exists - (progn - (set-buffer edebug-buffer) - (if (memq edebug-execution-mode '(go Go-nonstop)) - (edebug-overlay-arrow)) - (setq buffer-read-only edebug-buffer-read-only) - (use-local-map edebug-outside-map) - ) - ;; gotta have a buffer to let its buffer local variables be set - (get-buffer-create " bogus edebug buffer")) - ));; inner let - - ;; Reset global vars to outside values, in case they have been changed. - (setq - last-command-char edebug-outside-last-command-char - last-command-event edebug-outside-last-command-event - last-command edebug-outside-last-command - this-command edebug-outside-this-command - unread-command-char edebug-outside-unread-command-char - unread-command-event edebug-outside-unread-command-event - unread-command-events edebug-outside-unread-command-events - last-input-char edebug-outside-last-input-char - last-input-event edebug-outside-last-input-event - last-event-frame edebug-outside-last-event-frame - last-nonmenu-event edebug-outside-last-nonmenu-event - track-mouse edebug-outside-track-mouse - - standard-output edebug-outside-standard-output - standard-input edebug-outside-standard-input - defining-kbd-macro edebug-outside-defining-kbd-macro - )) - )) - - -;;; Display related functions - -(defun edebug-adjust-window (old-start) - ;; If pos is not visible, adjust current window to fit following context. -;;; (message "window: %s old-start: %s window-start: %s pos: %s" -;;; (selected-window) old-start (window-start) (point)) (sit-for 5) - (if (not (pos-visible-in-window-p)) - (progn - ;; First try old-start - (if old-start - (set-window-start (selected-window) old-start)) - (if (not (pos-visible-in-window-p)) - (progn -;; (message "resetting window start") (sit-for 2) - (set-window-start - (selected-window) - (save-excursion - (forward-line - (if (< (point) (window-start)) -1 ; one line before if in back - (- (/ (window-height) 2)) ; center the line moving forward - )) - (beginning-of-line) - (point))))))) - (window-start)) - - - -(defconst edebug-arrow-alist - '((Continue-fast . "=") - (Trace-fast . "-") - (continue . ">") - (trace . "->") - (step . "=>") - (next . "=>") - (go . "<>") - (Go-nonstop . "..") ; not used - ) - "Association list of arrows for each edebug mode.") - -(defun edebug-overlay-arrow () - ;; Set up the overlay arrow at beginning-of-line in current buffer. - ;; The arrow string is derived from edebug-arrow-alist and - ;; edebug-execution-mode. - (let ((pos (save-excursion (beginning-of-line) (point)))) - (setq overlay-arrow-string - (cdr (assq edebug-execution-mode edebug-arrow-alist))) - (setq overlay-arrow-position (make-marker)) - (set-marker overlay-arrow-position pos (current-buffer)))) - - -(defun edebug-toggle-save-all-windows () - "Toggle the saving and restoring of all windows. -Also, each time you toggle it on, the inside and outside window -configurations become the same as the current configuration." - (interactive) - (setq edebug-save-windows (not edebug-save-windows)) - (if edebug-save-windows - (setq edebug-inside-windows - (setq edebug-outside-windows - (edebug-current-windows - edebug-save-windows)))) - (message "Window saving is %s for all windows." - (if edebug-save-windows "on" "off"))) - -(defmacro edebug-changing-windows (&rest body) - (` (let ((window (selected-window))) - (setq edebug-inside-windows (edebug-current-windows t)) - (edebug-set-windows edebug-outside-windows) - (,@ body) ;; Code to change edebug-save-windows - (setq edebug-outside-windows (edebug-current-windows - edebug-save-windows)) - ;; Problem: what about outside windows that are deleted inside? - (edebug-set-windows edebug-inside-windows)))) - -(defun edebug-toggle-save-selected-window () - "Toggle the saving and restoring of the selected window. -Also, each time you toggle it on, the inside and outside window -configurations become the same as the current configuration." - (interactive) - (cond - ((eq t edebug-save-windows) - ;; Save all outside windows except the selected one. - ;; Remove (selected-window) from outside-windows. - (edebug-changing-windows - (setq edebug-save-windows (delq window (edebug-window-list))))) - - ((memq (selected-window) edebug-save-windows) - (setq edebug-outside-windows - (delq (assq (selected-window) edebug-outside-windows) - edebug-outside-windows)) - (setq edebug-save-windows - (delq (selected-window) edebug-save-windows))) - (t ; Save a new window. - (edebug-changing-windows - (setq edebug-save-windows (cons window edebug-save-windows))))) - - (message "Window saving is %s for %s." - (if (memq (selected-window) edebug-save-windows) - "on" "off") - (selected-window))) - -(defun edebug-toggle-save-windows (arg) - "Toggle the saving and restoring of windows. -With prefix, toggle for just the selected window. -Otherwise, toggle for all windows." - (interactive "P") - (if arg - (edebug-toggle-save-selected-window) - (edebug-toggle-save-all-windows))) - - -(defun edebug-where () - "Show the debug windows and where we stopped in the program." - (interactive) - (if (not edebug-active) - (error "Edebug is not active")) - ;; Restore the window configuration to what it last was inside. - ;; But it is not always set. - experiment - ;;(if edebug-inside-windows - ;; (edebug-set-windows edebug-inside-windows)) - (edebug-pop-to-buffer edebug-buffer) - (goto-char edebug-point)) - -(defun edebug-view-outside () - "Change to the outside window configuration." - (interactive) - (if (not edebug-active) - (error "Edebug is not active")) - (setq edebug-inside-windows - (edebug-current-windows edebug-save-windows)) - (edebug-set-windows edebug-outside-windows) - (goto-char edebug-outside-point) - (message "Window configuration outside of Edebug. Return with %s" - (substitute-command-keys "\\\\[edebug-where]"))) - - -(defun edebug-bounce-point (arg) - "Bounce the point in the outside current buffer. -If prefix arg is supplied, sit for that many seconds before returning. -The default is one second." - (interactive "p") - (if (not edebug-active) - (error "Edebug is not active")) - (save-excursion - ;; If the buffer's currently displayed, avoid set-window-configuration. - (save-window-excursion - (edebug-pop-to-buffer edebug-outside-buffer) - (goto-char edebug-outside-point) - (message "Current buffer: %s Point: %s Mark: %s" - (current-buffer) (point) - (if (marker-buffer (edebug-mark-marker)) - (marker-position (edebug-mark-marker)) "")) - (edebug-sit-for arg) - (edebug-pop-to-buffer edebug-buffer (car edebug-window-data))))) - - -;; Joe Wells, here is a start at your idea of adding a buffer to the internal -;; display list. Still need to use this list in edebug-display. - -'(defvar edebug-display-buffer-list nil - "List of buffers that edebug will display when it is active.") - -'(defun edebug-display-buffer (buffer) - "Toggle display of a buffer inside of edebug." - (interactive "bBuffer: ") - (let ((already-displaying (memq buffer edebug-display-buffer-list))) - (setq edebug-display-buffer-list - (if already-displaying - (delq buffer edebug-display-buffer-list) - (cons buffer edebug-display-buffer-list))) - (message "Displaying %s %s" buffer - (if already-displaying "off" "on")))) - -;;; Breakpoint related functions - -(defun edebug-find-stop-point () - ;; Return (function . index) of the nearest edebug stop point. - (let* ((edebug-def-name (edebug-form-data-symbol)) - (edebug-data - (let ((data (get edebug-def-name 'edebug))) - (if (or (null data) (markerp data)) - (error "%s is not instrumented for Edebug" edebug-def-name)) - data)) ; we could do it automatically, if data is a marker. - ;; pull out parts of edebug-data. - (edebug-def-mark (car edebug-data)) - ;; (edebug-breakpoints (car (cdr edebug-data))) - - (offset-vector (nth 2 edebug-data)) - (offset (- (save-excursion - (if (looking-at "[ \t]") - ;; skip backwards until non-whitespace, or bol - (skip-chars-backward " \t")) - (point)) - edebug-def-mark)) - len i) - ;; the offsets are in order so we can do a linear search - (setq len (length offset-vector)) - (setq i 0) - (while (and (< i len) (> offset (aref offset-vector i))) - (setq i (1+ i))) - (if (and (< i len) - (<= offset (aref offset-vector i))) - ;; return the relevant info - (cons edebug-def-name i) - (message "Point is not on an expression in %s." - edebug-def-name) - ))) - - -(defun edebug-next-breakpoint () - "Move point to the next breakpoint, or first if none past point." - (interactive) - (let ((edebug-stop-point (edebug-find-stop-point))) - (if edebug-stop-point - (let* ((edebug-def-name (car edebug-stop-point)) - (index (cdr edebug-stop-point)) - (edebug-data (get edebug-def-name 'edebug)) - - ;; pull out parts of edebug-data - (edebug-def-mark (car edebug-data)) - (edebug-breakpoints (car (cdr edebug-data))) - (offset-vector (nth 2 edebug-data)) - breakpoint) - (if (not edebug-breakpoints) - (message "No breakpoints in this function.") - (let ((breaks edebug-breakpoints)) - (while (and breaks - (<= (car (car breaks)) index)) - (setq breaks (cdr breaks))) - (setq breakpoint - (if breaks - (car breaks) - ;; goto the first breakpoint - (car edebug-breakpoints))) - (goto-char (+ edebug-def-mark - (aref offset-vector (car breakpoint)))) - - (message "%s" - (concat (if (nth 2 breakpoint) - "Temporary " "") - (if (car (cdr breakpoint)) - (format "Condition: %s" - (edebug-safe-prin1-to-string - (car (cdr breakpoint)))) - ""))) - )))))) - - -(defun edebug-modify-breakpoint (flag &optional condition temporary) - "Modify the breakpoint for the form at point or after it according -to FLAG: set if t, clear if nil. Then move to that point. -If CONDITION or TEMPORARY are non-nil, add those attributes to -the breakpoint. " - (let ((edebug-stop-point (edebug-find-stop-point))) - (if edebug-stop-point - (let* ((edebug-def-name (car edebug-stop-point)) - (index (cdr edebug-stop-point)) - (edebug-data (get edebug-def-name 'edebug)) - - ;; pull out parts of edebug-data - (edebug-def-mark (car edebug-data)) - (edebug-breakpoints (car (cdr edebug-data))) - (offset-vector (nth 2 edebug-data)) - present) - ;; delete it either way - (setq present (assq index edebug-breakpoints)) - (setq edebug-breakpoints (delq present edebug-breakpoints)) - (if flag - (progn - ;; add it to the list and resort - (setq edebug-breakpoints - (edebug-sort-alist - (cons - (list index condition temporary) - edebug-breakpoints) '<)) - (if condition - (message "Breakpoint set in %s with condition: %s" - edebug-def-name condition) - (message "Breakpoint set in %s" edebug-def-name))) - (if present - (message "Breakpoint unset in %s" edebug-def-name) - (message "No breakpoint here"))) - - (setcar (cdr edebug-data) edebug-breakpoints) - (goto-char (+ edebug-def-mark (aref offset-vector index))) - )))) - -(defun edebug-set-breakpoint (arg) - "Set the breakpoint of nearest sexp. -With prefix argument, make it a temporary breakpoint." - (interactive "P") - (edebug-modify-breakpoint t nil arg)) - -(defun edebug-unset-breakpoint () - "Clear the breakpoint of nearest sexp." - (interactive) - (edebug-modify-breakpoint nil)) - - -;; For emacs 18, no read-expression-history -(defun edebug-set-conditional-breakpoint (arg condition) - "Set a conditional breakpoint at nearest sexp. -The condition is evaluated in the outside context. -With prefix argument, make it a temporary breakpoint." - ;; (interactive "P\nxCondition: ") - (interactive - (list - current-prefix-arg - ;; Edit previous condition as follows, but it is cumbersome: - (let ((edebug-stop-point (edebug-find-stop-point))) - (if edebug-stop-point - (let* ((edebug-def-name (car edebug-stop-point)) - (index (cdr edebug-stop-point)) - (edebug-data (get edebug-def-name 'edebug)) - (edebug-breakpoints (car (cdr edebug-data))) - (edebug-break-data (assq index edebug-breakpoints)) - (edebug-break-condition (car (cdr edebug-break-data)))) - (read-minibuffer - (format "Condition in %s: " edebug-def-name) - (if edebug-break-condition - (format "%s" edebug-break-condition) - (format "")))))))) - (edebug-modify-breakpoint t condition arg)) - - -(defun edebug-set-global-break-condition (expression) - (interactive (list (read-minibuffer - "Global Condition: " - (format "%s" edebug-global-break-condition)))) - (setq edebug-global-break-condition expression)) - - -;;; Mode switching functions - -(defun edebug-set-mode (mode shortmsg msg) - ;; Set the edebug mode to MODE. - ;; Display SHORTMSG, or MSG if not within edebug. - (if (eq (1+ edebug-recursion-depth) (recursion-depth)) - (progn - (setq edebug-execution-mode mode) - (message shortmsg) - ;; Continue execution - (exit-recursive-edit)) - ;; This is not terribly useful!! - (setq edebug-next-execution-mode mode) - (message msg))) - - -(defalias 'edebug-step-through-mode 'edebug-step-mode) - -(defun edebug-step-mode () - "Proceed to next stop point." - (interactive) - (edebug-set-mode 'step "" "Edebug will stop at next stop point.")) - -(defun edebug-next-mode () - "Proceed to next `after' stop point." - (interactive) - (edebug-set-mode 'next "" "Edebug will stop after next eval.")) - -(defun edebug-go-mode (arg) - "Go, evaluating until break. -With prefix ARG, set temporary break at current point and go." - (interactive "P") - (if arg - (edebug-set-breakpoint t)) - (edebug-set-mode 'go "Go..." "Edebug will go until break.")) - -(defun edebug-Go-nonstop-mode () - "Go, evaluating without debugging." - (interactive) - (edebug-set-mode 'Go-nonstop "Go-Nonstop..." - "Edebug will not stop at breaks.")) - - -(defun edebug-trace-mode () - "Begin trace mode." - (interactive) - (edebug-set-mode 'trace "Tracing..." "Edebug will trace with pause.")) - -(defun edebug-Trace-fast-mode () - "Trace with no wait at each step." - (interactive) - (edebug-set-mode 'Trace-fast - "Trace fast..." "Edebug will trace without pause.")) - -(defun edebug-continue-mode () - "Begin continue mode." - (interactive) - (edebug-set-mode 'continue "Continue..." - "Edebug will pause at breakpoints.")) - -(defun edebug-Continue-fast-mode () - "Trace with no wait at each step." - (interactive) - (edebug-set-mode 'Continue-fast "Continue fast..." - "Edebug will stop and go at breakpoints.")) - -;; ------------------------------------------------------------ -;; The following use the mode changing commands and breakpoints. - - -(defun edebug-goto-here () - "Proceed to this stop point." - (interactive) - (edebug-go-mode t)) - - -(defun edebug-stop () - "Stop execution and do not continue. -Useful for exiting from trace or continue loop." - (interactive) - (message "Stop")) - - -'(defun edebug-forward () - "Proceed to the exit of the next expression to be evaluated." - (interactive) - (edebug-set-mode - 'forward "Forward" - "Edebug will stop after exiting the next expression.")) - - -(defun edebug-forward-sexp (arg) - "Proceed from the current point to the end of the ARGth sexp ahead. -If there are not ARG sexps ahead, then do edebug-step-out." - (interactive "p") - (condition-case nil - (let ((parse-sexp-ignore-comments t)) - ;; Call forward-sexp repeatedly until done or failure. - (forward-sexp arg) - (edebug-go-mode t)) - (error - (edebug-step-out) - ))) - -(defun edebug-step-out () - "Proceed from the current point to the end of the containing sexp. -If there is no containing sexp that is not the top level defun, -go to the end of the last sexp, or if that is the same point, then step." - (interactive) - (condition-case nil - (let ((parse-sexp-ignore-comments t)) - (up-list 1) - (save-excursion - ;; Is there still a containing expression? - (up-list 1)) - (edebug-go-mode t)) - (error - ;; At top level - 1, so first check if there are more sexps at this level. - (let ((start-point (point))) -;; (up-list 1) - (down-list -1) - (if (= (point) start-point) - (edebug-step-mode) ; No more at this level, so step. - (edebug-go-mode t) - ))))) - -(defun edebug-instrument-function (func) - ;; Func should be a function symbol. - ;; Return the function symbol, or nil if not instrumented. - (let ((func-marker)) - (setq func-marker (get func 'edebug)) - (cond - ((markerp func-marker) - ;; It is uninstrumented, so instrument it. - (save-excursion - (set-buffer (marker-buffer func-marker)) - (goto-char func-marker) - (edebug-eval-top-level-form) - func)) - ((consp func-marker) - (message "%s is already instrumented." func) - func) - (t - ;; We could try harder, e.g. do a tags search. - (error "Don't know where %s is defined" func) - nil)))) - -(defun edebug-instrument-callee () - "Instrument the definition of the function or macro about to be called. -Do this when stopped before the form or it will be too late. -One side effect of using this command is that the next time the -function or macro is called, Edebug will be called there as well." - (interactive) - (if (not (looking-at "\(")) - (error "You must be before a list form") - (let ((func - (save-excursion - (down-list 1) - (if (looking-at "\(") - (edebug-form-data-name - (edebug-get-form-data-entry (point))) - (edebug-original-read (current-buffer)))))) - (edebug-instrument-function func)))) - - -(defun edebug-step-in () - "Step into the definition of the function or macro about to be called. -This first does `edebug-instrument-callee' to ensure that it is -instrumented. Then it does `edebug-on-entry' and switches to `go' mode." - (interactive) - (let ((func (edebug-instrument-callee))) - (if func - (progn - (edebug-on-entry func 'temp) - (edebug-go-mode nil))))) - -(defun edebug-on-entry (function &optional flag) - "Cause Edebug to stop when FUNCTION is called. -With prefix argument, make this temporary so it is automatically -cancelled the first time the function is entered." - (interactive "aEdebug on entry to: \nP") - ;; Could store this in the edebug data instead. - (put function 'edebug-on-entry (if flag 'temp t))) - -(defun cancel-edebug-on-entry (function) - (interactive "aEdebug on entry to: ") - (put function 'edebug-on-entry nil)) - - -(if (not (fboundp 'edebug-original-debug-on-entry)) - (fset 'edebug-original-debug-on-entry (symbol-function 'debug-on-entry))) -'(fset 'debug-on-entry 'edebug-debug-on-entry) ;; Should we do this? -;; Also need edebug-cancel-debug-on-entry - -'(defun edebug-debug-on-entry (function) - "Request FUNCTION to invoke debugger each time it is called. -If the user continues, FUNCTION's execution proceeds. -Works by modifying the definition of FUNCTION, -which must be written in Lisp, not predefined. -Use `cancel-debug-on-entry' to cancel the effect of this command. -Redefining FUNCTION also does that. - -This version is from Edebug. If the function is instrumented for -Edebug, it calls `edebug-on-entry'" - (interactive "aDebug on entry (to function): ") - (let ((func-data (get function 'edebug))) - (if (or (null func-data) (markerp func-data)) - (edebug-original-debug-on-entry function) - (edebug-on-entry function)))) - - -(defun edebug-top-level-nonstop () - "Set mode to Go-nonstop, and exit to top-level. -This is useful for exiting even if unwind-protect code may be executed." - (interactive) - (setq edebug-execution-mode 'Go-nonstop) - (top-level)) - - -;;(defun edebug-exit-out () -;; "Go until the current function exits." -;; (interactive) -;; (edebug-set-mode 'exiting "Exit...")) - - -;;; The following initial mode setting definitions are not used yet. - -'(defconst edebug-initial-mode-alist - '((edebug-Continue-fast . Continue-fast) - (edebug-Trace-fast . Trace-fast) - (edebug-continue . continue) - (edebug-trace . trace) - (edebug-go . go) - (edebug-step-through . step) - (edebug-Go-nonstop . Go-nonstop) - ) - "Association list between commands and the modes they set.") - - -'(defun edebug-set-initial-mode () - "Ask for the initial mode of the enclosing function. -The mode is requested via the key that would be used to set the mode in -edebug-mode." - (interactive) - (let* ((this-function (edebug-which-function)) - (keymap (if (eq edebug-mode-map (current-local-map)) - edebug-mode-map)) - (old-mode (or (get this-function 'edebug-initial-mode) - edebug-initial-mode)) - (key (read-key-sequence - (format - "Change initial edebug mode for %s from %s (%s) to (enter key): " - this-function - old-mode - (where-is-internal - (car (rassq old-mode edebug-initial-mode-alist)) - keymap 'firstonly - )))) - (mode (cdr (assq (key-binding key) edebug-initial-mode-alist))) - ) - (if (and mode - (or (get this-function 'edebug-initial-mode) - (not (eq mode edebug-initial-mode)))) - (progn - (put this-function 'edebug-initial-mode mode) - (message "Initial mode for %s is now: %s" - this-function mode)) - (error "Key must map to one of the mode changing commands") - ))) - -;;; Evaluation of expressions - -(def-edebug-spec edebug-outside-excursion t) - -(defmacro edebug-outside-excursion (&rest body) - "Evaluate an expression list in the outside context. -Return the result of the last expression." - (` (save-excursion ; of current-buffer - (if edebug-save-windows - (progn - ;; After excursion, we will - ;; restore to current window configuration. - (setq edebug-inside-windows - (edebug-current-windows edebug-save-windows)) - ;; Restore outside windows. - (edebug-set-windows edebug-outside-windows))) - - (set-buffer edebug-buffer) ; why? - ;; (use-local-map edebug-outside-map) - (store-match-data edebug-outside-match-data) - ;; Restore outside context. - (let (;; (edebug-inside-map (current-local-map)) ;; restore map?? - (last-command-char edebug-outside-last-command-char) - (last-command-event edebug-outside-last-command-event) - (last-command edebug-outside-last-command) - (this-command edebug-outside-this-command) - (unread-command-char edebug-outside-unread-command-char) - (unread-command-event edebug-outside-unread-command-event) - (unread-command-events edebug-outside-unread-command-events) - (last-input-char edebug-outside-last-input-char) - (last-input-event edebug-outside-last-input-event) - (last-event-frame edebug-outside-last-event-frame) - (last-nonmenu-event edebug-outside-last-nonmenu-event) - (track-mouse edebug-outside-track-mouse) - (standard-output edebug-outside-standard-output) - (standard-input edebug-outside-standard-input) - - (executing-kbd-macro edebug-outside-executing-macro) - (defining-kbd-macro edebug-outside-defining-kbd-macro) - (pre-command-hook edebug-outside-pre-command-hook) - (post-command-hook edebug-outside-post-command-hook) - (post-command-idle-hook edebug-outside-post-command-idle-hook) - - ;; See edebug-display - (overlay-arrow-position edebug-outside-o-a-p) - (overlay-arrow-string edebug-outside-o-a-s) - (cursor-in-echo-area edebug-outside-c-i-e-a) - ) - (unwind-protect - (save-excursion ; of edebug-buffer - (set-buffer edebug-outside-buffer) - (goto-char edebug-outside-point) - (if (marker-buffer (edebug-mark-marker)) - (set-marker (edebug-mark-marker) edebug-outside-mark)) - (,@ body)) - - ;; Back to edebug-buffer. Restore rest of inside context. - ;; (use-local-map edebug-inside-map) - (if edebug-save-windows - ;; Restore inside windows. - (edebug-set-windows edebug-inside-windows)) - - ;; Save values that may have been changed. - (setq - edebug-outside-last-command-char last-command-char - edebug-outside-last-command-event last-command-event - edebug-outside-last-command last-command - edebug-outside-this-command this-command - edebug-outside-unread-command-char unread-command-char - edebug-outside-unread-command-event unread-command-event - edebug-outside-unread-command-events unread-command-events - edebug-outside-last-input-char last-input-char - edebug-outside-last-input-event last-input-event - edebug-outside-last-event-frame last-event-frame - edebug-outside-last-nonmenu-event last-nonmenu-event - edebug-outside-track-mouse track-mouse - edebug-outside-standard-output standard-output - edebug-outside-standard-input standard-input - - edebug-outside-executing-macro executing-kbd-macro - edebug-outside-defining-kbd-macro defining-kbd-macro - edebug-outside-pre-command-hook pre-command-hook - edebug-outside-post-command-hook post-command-hook - edebug-outside-post-command-idle-hook post-command-idle-hook - - edebug-outside-o-a-p overlay-arrow-position - edebug-outside-o-a-s overlay-arrow-string - edebug-outside-c-i-e-a cursor-in-echo-area - ))) ; let - ))) - -(defvar cl-debug-env nil) ;; defined in cl; non-nil when lexical env used. - -(defun edebug-eval (edebug-expr) - ;; Are there cl lexical variables active? - (if cl-debug-env - (eval (cl-macroexpand-all edebug-expr cl-debug-env)) - (eval edebug-expr))) - -(defun edebug-safe-eval (edebug-expr) - ;; Evaluate EXPR safely. - ;; If there is an error, a string is returned describing the error. - (condition-case edebug-err - (edebug-eval edebug-expr) - (error (edebug-format "%s: %s" ;; could - (get (car edebug-err) 'error-message) - (car (cdr edebug-err)))))) - -;;; Printing - -;; Replace printing functions. - -;; obsolete names -(defalias 'edebug-install-custom-print-funcs 'edebug-install-custom-print) -(defalias 'edebug-reset-print-funcs 'edebug-uninstall-custom-print) -(defalias 'edebug-uninstall-custom-print-funcs 'edebug-uninstall-custom-print) - -(defun edebug-install-custom-print () - "Replace print functions used by Edebug with custom versions." - ;; Modifying the custom print functions, or changing print-length, - ;; print-level, print-circle, custom-print-list or custom-print-vector - ;; have immediate effect. - (interactive) - (require 'cust-print) - (defalias 'edebug-prin1 'custom-prin1) - (defalias 'edebug-print 'custom-print) - (defalias 'edebug-prin1-to-string 'custom-prin1-to-string) - (defalias 'edebug-format 'custom-format) - (defalias 'edebug-message 'custom-message) - "Installed") - -(eval-and-compile - (defun edebug-uninstall-custom-print () - "Replace edebug custom print functions with internal versions." - (interactive) - (defalias 'edebug-prin1 'prin1) - (defalias 'edebug-print 'print) - (defalias 'edebug-prin1-to-string 'prin1-to-string) - (defalias 'edebug-format 'format) - (defalias 'edebug-message 'message) - "Uninstalled") - - ;; Default print functions are the same as Emacs'. - (edebug-uninstall-custom-print)) - - -(defun edebug-report-error (edebug-value) - ;; Print an error message like command level does. - ;; This also prints the error name if it has no error-message. - (message "%s: %s" - (or (get (car edebug-value) 'error-message) - (format "peculiar error (%s)" (car edebug-value))) - (mapconcat (function (lambda (edebug-arg) - ;; continuing after an error may - ;; complain about edebug-arg. why?? - (prin1-to-string edebug-arg))) - (cdr edebug-value) ", "))) - -;; Define here in case they are not already defined. -(defvar print-level nil) -(defvar print-circle nil) -(defvar print-readably) ;; defined by XEmacs -;; Alternatively, we could change the definition of -;; edebug-safe-prin1-to-string to only use these if defined. - -(defun edebug-safe-prin1-to-string (value) - (let ((print-escape-newlines t) - (print-length (or edebug-print-length print-length)) - (print-level (or edebug-print-level print-level)) - (print-circle (or edebug-print-circle print-circle)) - (print-readably nil)) ;; XEmacs uses this. - (edebug-prin1-to-string value))) - -(defun edebug-compute-previous-result (edebug-previous-value) - (setq edebug-previous-result - (if (numberp edebug-previous-value) - (format "Result: %s" edebug-previous-value) - (if edebug-unwrap-results - (setq edebug-previous-value - (edebug-unwrap* edebug-previous-value))) - (concat "Result: " - (edebug-safe-prin1-to-string edebug-previous-value))))) - -(defun edebug-previous-result () - "Print the previous result." - (interactive) - (message "%s" edebug-previous-result)) - -;;; Read, Eval and Print - -(defun edebug-eval-expression (edebug-expr) - "Evaluate an expression in the outside environment. -If interactive, prompt for the expression. -Print result in minibuffer." - (interactive "xEval: ") - (princ - (edebug-outside-excursion - (setq values (cons (edebug-eval edebug-expr) values)) - (edebug-safe-prin1-to-string (car values))))) - -(defun edebug-eval-last-sexp () - "Evaluate sexp before point in the outside environment; -print value in minibuffer." - (interactive) - (edebug-eval-expression (edebug-last-sexp))) - -(defun edebug-eval-print-last-sexp () - "Evaluate sexp before point in the outside environment; -print value into current buffer." - (interactive) - (let* ((edebug-form (edebug-last-sexp)) - (edebug-result-string - (edebug-outside-excursion - (edebug-safe-prin1-to-string (edebug-safe-eval edebug-form)))) - (standard-output (current-buffer))) - (princ "\n") - ;; princ the string to get rid of quotes. - (princ edebug-result-string) - (princ "\n") - )) - -;;; Edebug Minor Mode - -;; Global GUD bindings for all emacs-lisp-mode buffers. -(define-key emacs-lisp-mode-map "\C-x\C-a\C-s" 'edebug-step-mode) -(define-key emacs-lisp-mode-map "\C-x\C-a\C-n" 'edebug-next-mode) -(define-key emacs-lisp-mode-map "\C-x\C-a\C-c" 'edebug-go-mode) -(define-key emacs-lisp-mode-map "\C-x\C-a\C-l" 'edebug-where) - - -(defvar edebug-mode-map nil) -(if edebug-mode-map - nil - (progn - (setq edebug-mode-map (copy-keymap emacs-lisp-mode-map)) - ;; control - (define-key edebug-mode-map " " 'edebug-step-mode) - (define-key edebug-mode-map "n" 'edebug-next-mode) - (define-key edebug-mode-map "g" 'edebug-go-mode) - (define-key edebug-mode-map "G" 'edebug-Go-nonstop-mode) - (define-key edebug-mode-map "t" 'edebug-trace-mode) - (define-key edebug-mode-map "T" 'edebug-Trace-fast-mode) - (define-key edebug-mode-map "c" 'edebug-continue-mode) - (define-key edebug-mode-map "C" 'edebug-Continue-fast-mode) - - ;;(define-key edebug-mode-map "f" 'edebug-forward) not implemented - (define-key edebug-mode-map "f" 'edebug-forward-sexp) - (define-key edebug-mode-map "h" 'edebug-goto-here) - - (define-key edebug-mode-map "I" 'edebug-instrument-callee) - (define-key edebug-mode-map "i" 'edebug-step-in) - (define-key edebug-mode-map "o" 'edebug-step-out) - - ;; quitting and stopping - (define-key edebug-mode-map "q" 'top-level) - (define-key edebug-mode-map "Q" 'edebug-top-level-nonstop) - (define-key edebug-mode-map "a" 'abort-recursive-edit) - (define-key edebug-mode-map "S" 'edebug-stop) - - ;; breakpoints - (define-key edebug-mode-map "b" 'edebug-set-breakpoint) - (define-key edebug-mode-map "u" 'edebug-unset-breakpoint) - (define-key edebug-mode-map "B" 'edebug-next-breakpoint) - (define-key edebug-mode-map "x" 'edebug-set-conditional-breakpoint) - (define-key edebug-mode-map "X" 'edebug-set-global-break-condition) - - ;; evaluation - (define-key edebug-mode-map "r" 'edebug-previous-result) - (define-key edebug-mode-map "e" 'edebug-eval-expression) - (define-key edebug-mode-map "\C-x\C-e" 'edebug-eval-last-sexp) - (define-key edebug-mode-map "E" 'edebug-visit-eval-list) - - ;; views - (define-key edebug-mode-map "w" 'edebug-where) - (define-key edebug-mode-map "v" 'edebug-view-outside) ;; maybe obsolete?? - (define-key edebug-mode-map "p" 'edebug-bounce-point) - (define-key edebug-mode-map "P" 'edebug-view-outside) ;; same as v - (define-key edebug-mode-map "W" 'edebug-toggle-save-windows) - - ;; misc - (define-key edebug-mode-map "?" 'edebug-help) - (define-key edebug-mode-map "d" 'edebug-backtrace) - - (define-key edebug-mode-map "-" 'negative-argument) - - ;; statistics - (define-key edebug-mode-map "=" 'edebug-temp-display-freq-count) - - ;; GUD bindings - (define-key edebug-mode-map "\C-c\C-s" 'edebug-step-mode) - (define-key edebug-mode-map "\C-c\C-n" 'edebug-next-mode) - (define-key edebug-mode-map "\C-c\C-c" 'edebug-go-mode) - - (define-key edebug-mode-map "\C-x " 'edebug-set-breakpoint) - (define-key edebug-mode-map "\C-c\C-d" 'edebug-unset-breakpoint) - (define-key edebug-mode-map "\C-c\C-t" - (function (lambda () (edebug-set-breakpoint t)))) - (define-key edebug-mode-map "\C-c\C-l" 'edebug-where) - )) - -;; Autoloading these global bindings doesn't make sense because -;; they cannot be used anyway unless Edebug is already loaded and active. - -(defvar global-edebug-prefix "\^XX" - "Prefix key for global edebug commands, available from any buffer.") - -(defvar global-edebug-map nil - "Global map of edebug commands, available from any buffer.") - -(if global-edebug-map - nil - (setq global-edebug-map (make-sparse-keymap)) - - (global-unset-key global-edebug-prefix) - (global-set-key global-edebug-prefix global-edebug-map) - - (define-key global-edebug-map " " 'edebug-step-mode) - (define-key global-edebug-map "g" 'edebug-go-mode) - (define-key global-edebug-map "G" 'edebug-Go-nonstop-mode) - (define-key global-edebug-map "t" 'edebug-trace-mode) - (define-key global-edebug-map "T" 'edebug-Trace-fast-mode) - (define-key global-edebug-map "c" 'edebug-continue-mode) - (define-key global-edebug-map "C" 'edebug-Continue-fast-mode) - - ;; breakpoints - (define-key global-edebug-map "b" 'edebug-set-breakpoint) - (define-key global-edebug-map "u" 'edebug-unset-breakpoint) - (define-key global-edebug-map "x" 'edebug-set-conditional-breakpoint) - (define-key global-edebug-map "X" 'edebug-set-global-break-condition) - - ;; views - (define-key global-edebug-map "w" 'edebug-where) - (define-key global-edebug-map "W" 'edebug-toggle-save-windows) - - ;; quitting - (define-key global-edebug-map "q" 'top-level) - (define-key global-edebug-map "Q" 'edebug-top-level-nonstop) - (define-key global-edebug-map "a" 'abort-recursive-edit) - - ;; statistics - (define-key global-edebug-map "=" 'edebug-display-freq-count) - ) - -(defun edebug-help () - (interactive) - (describe-function 'edebug-mode)) - -(defun edebug-mode () - "Mode for Emacs Lisp buffers while in Edebug. - -In addition to all Emacs Lisp commands (except those that modify the -buffer) there are local and global key bindings to several Edebug -specific commands. E.g. `edebug-step-mode' is bound to \\[edebug-step-mode] -in the Edebug buffer and \\\\[edebug-step-mode] in any buffer. - -Also see bindings for the eval list buffer, *edebug*. - -The edebug buffer commands: -\\{edebug-mode-map} - -Global commands prefixed by `global-edebug-prefix': -\\{global-edebug-map} - -Options: -edebug-setup-hook -edebug-all-defs -edebug-all-forms -edebug-save-windows -edebug-save-displayed-buffer-points -edebug-initial-mode -edebug-trace -edebug-test-coverage -edebug-continue-kbd-macro -edebug-print-length -edebug-print-level -edebug-print-circle -edebug-on-error -edebug-on-quit -edebug-on-signal -edebug-unwrap-results -edebug-global-break-condition -" - (use-local-map edebug-mode-map)) - -;;; edebug eval list mode - -;; A list of expressions and their evaluations is displayed in *edebug*. - -(defun edebug-eval-result-list () - "Return a list of evaluations of edebug-eval-list" - ;; Assumes in outside environment. - ;; Don't do any edebug things now. - (let ((edebug-execution-mode 'Go-nonstop) - (edebug-trace nil)) - (mapcar 'edebug-safe-eval edebug-eval-list))) - -(defun edebug-eval-display-list (edebug-eval-result-list) - ;; Assumes edebug-eval-buffer exists. - (let ((edebug-eval-list-temp edebug-eval-list) - (standard-output edebug-eval-buffer) - (edebug-comment-line - (format ";%s\n" (make-string (- (window-width) 2) ?-)))) - (set-buffer edebug-eval-buffer) - (erase-buffer) - (while edebug-eval-list-temp - (prin1 (car edebug-eval-list-temp)) (terpri) - (prin1 (car edebug-eval-result-list)) (terpri) - (princ edebug-comment-line) - (setq edebug-eval-list-temp (cdr edebug-eval-list-temp)) - (setq edebug-eval-result-list (cdr edebug-eval-result-list))) - (edebug-pop-to-buffer edebug-eval-buffer) - )) - -(defun edebug-create-eval-buffer () - (if (not (and edebug-eval-buffer (buffer-name edebug-eval-buffer))) - (progn - (set-buffer (setq edebug-eval-buffer (get-buffer-create "*edebug*"))) - (edebug-eval-mode)))) - -;; Should generalize this to be callable outside of edebug -;; with calls in user functions, e.g. (edebug-eval-display) - -(defun edebug-eval-display (edebug-eval-result-list) - "Display expressions and evaluations in EVAL-LIST. -It modifies the context by popping up the eval display." - (if edebug-eval-result-list - (progn - (edebug-create-eval-buffer) - (edebug-eval-display-list edebug-eval-result-list) - ))) - -(defun edebug-eval-redisplay () - "Redisplay eval list in outside environment. -May only be called from within edebug-recursive-edit." - (edebug-create-eval-buffer) - (edebug-outside-excursion - (edebug-eval-display-list (edebug-eval-result-list)) - )) - -(defun edebug-visit-eval-list () - (interactive) - (edebug-eval-redisplay) - (edebug-pop-to-buffer edebug-eval-buffer)) - - -(defun edebug-update-eval-list () - "Replace the evaluation list with the sexps now in the eval buffer." - (interactive) - (let ((starting-point (point)) - new-list) - (goto-char (point-min)) - ;; get the first expression - (edebug-skip-whitespace) - (if (not (eobp)) - (progn - (forward-sexp 1) - (setq new-list (cons (edebug-last-sexp) new-list)))) - - (while (re-search-forward "^;" nil t) - (forward-line 1) - (skip-chars-forward " \t\n\r") - (if (and (/= ?\; (following-char)) - (not (eobp))) - (progn - (forward-sexp 1) - (setq new-list (cons (edebug-last-sexp) new-list))))) - - (setq edebug-eval-list (nreverse new-list)) - (edebug-eval-redisplay) - (goto-char starting-point))) - - -(defun edebug-delete-eval-item () - "Delete the item under point and redisplay." - ;; could add arg to do repeatedly - (interactive) - (if (re-search-backward "^;" nil 'nofail) - (forward-line 1)) - (delete-region - (point) (progn (re-search-forward "^;" nil 'nofail) - (beginning-of-line) - (point))) - (edebug-update-eval-list)) - - - -(defvar edebug-eval-mode-map nil - "Keymap for edebug-eval-mode. Superset of lisp-interaction-mode.") - -(if edebug-eval-mode-map - nil - (setq edebug-eval-mode-map (copy-keymap lisp-interaction-mode-map)) - - (define-key edebug-eval-mode-map "\C-c\C-w" 'edebug-where) - (define-key edebug-eval-mode-map "\C-c\C-d" 'edebug-delete-eval-item) - (define-key edebug-eval-mode-map "\C-c\C-u" 'edebug-update-eval-list) - (define-key edebug-eval-mode-map "\C-x\C-e" 'edebug-eval-last-sexp) - (define-key edebug-eval-mode-map "\C-j" 'edebug-eval-print-last-sexp) - ) - - -(defun edebug-eval-mode () - "Mode for evaluation list buffer while in Edebug. - -In addition to all Interactive Emacs Lisp commands there are local and -global key bindings to several Edebug specific commands. E.g. -`edebug-step-mode' is bound to \\[edebug-step-mode] in the Edebug -buffer and \\\\[edebug-step-mode] in any buffer. - -Eval list buffer commands: -\\{edebug-eval-mode-map} - -Global commands prefixed by global-edebug-prefix: -\\{global-edebug-map} -" - (lisp-interaction-mode) - (setq major-mode 'edebug-eval-mode) - (setq mode-name "Edebug-Eval") - (use-local-map edebug-eval-mode-map)) - -;;; Interface with standard debugger. - -;; (setq debugger 'edebug) ; to use the edebug debugger -;; (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. - -(defun edebug (&optional edebug-arg-mode &rest debugger-args) - "Replacement for debug. -If we are running an edebugged function, -show where we last were. Otherwise call debug normally." -;; (message "entered: %s depth: %s edebug-recursion-depth: %s" -;; edebug-entered (recursion-depth) edebug-recursion-depth) (sit-for 1) - (if (and edebug-entered ; anything active? - (eq (recursion-depth) edebug-recursion-depth)) - (let (;; Where were we before the error occurred? - (edebug-offset-index (car edebug-offset-indices)) - ;; Bind variables required by edebug-display - (edebug-value (car debugger-args)) - edebug-breakpoints - edebug-break-data - edebug-break-condition - edebug-global-break - (edebug-break (null edebug-arg-mode)) ;; if called explicitly - ) - (edebug-display) - (if (eq edebug-arg-mode 'error) - nil - edebug-value)) - - ;; Otherwise call debug normally. - ;; Still need to remove extraneous edebug calls from stack. - (apply 'debug edebug-arg-mode debugger-args) - )) - - -(defun edebug-backtrace () - "Display a non-working backtrace. Better than nothing..." - (interactive) - (if (or (not edebug-backtrace-buffer) - (null (buffer-name edebug-backtrace-buffer))) - (setq edebug-backtrace-buffer - (generate-new-buffer "*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) - last-ok-point) - (backtrace) - - ;; 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 - - ;; 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))) - - ((looking-at "^ edebug") - (forward-line 1) - (delete-region last-ok-point (point)) - ))) - ))))) - - -;;; Trace display - -(defun edebug-trace-display (buf-name fmt &rest args) - "In buffer BUF-NAME, display FMT and ARGS at the end and make it visible. -The buffer is created if it does not exist. -You must include newlines in FMT to break lines, but one newline is appended." -;; e.g. -;; (edebug-trace-display "*trace-point*" -;; "saving: point = %s window-start = %s" -;; (point) (window-start)) - (let* ((oldbuf (current-buffer)) - (selected-window (selected-window)) - (buffer (get-buffer-create buf-name)) - buf-window) -;; (message "before pop-to-buffer") (sit-for 1) - (edebug-pop-to-buffer buffer) - (setq truncate-lines t) - (setq buf-window (selected-window)) - (goto-char (point-max)) - (insert (apply 'edebug-format fmt args) "\n") - ;; Make it visible. - (vertical-motion (- 1 (window-height))) - (set-window-start buf-window (point)) - (goto-char (point-max)) -;; (set-window-point buf-window (point)) -;; (edebug-sit-for 0) - (bury-buffer buffer) - (select-window selected-window) - (set-buffer oldbuf)) - buf-name) - - -(defun edebug-trace (fmt &rest args) - "Convenience call to edebug-trace-display using edebug-trace-buffer" - (apply 'edebug-trace-display edebug-trace-buffer fmt args)) - - -;;; Frequency count and coverage - -(defun edebug-display-freq-count () - "Display the frequency count data for each line of the current -definition. The frequency counts are inserted as comment lines after -each line, and you can undo all insertions with one `undo' command. - -The counts are inserted starting under the `(' before an expression -or the `)' after an expression, or on the last char of a symbol. -The counts are only displayed when they differ from previous counts on -the same line. - -If coverage is being tested, whenever all known results of an expression -are `eq', the char `=' will be appended after the count -for that expression. Note that this is always the case for an -expression only evaluated once. - -To clear the frequency count and coverage data for a definition, -reinstrument it." - (interactive) - (let* ((function (edebug-form-data-symbol)) - (counts (get function 'edebug-freq-count)) - (coverages (get function 'edebug-coverage)) - (data (get function 'edebug)) - (def-mark (car data)) ; mark at def start - (edebug-points (nth 2 data)) - (i (1- (length edebug-points))) - (last-index) - (first-index) - (start-of-line) - (start-of-count-line) - (last-count) - ) - (save-excursion - ;; Traverse in reverse order so offsets are correct. - (while (<= 0 i) - ;; Start at last expression in line. - (goto-char (+ def-mark (aref edebug-points i))) - (beginning-of-line) - (setq start-of-line (- (point) def-mark) - last-index i) - - ;; Find all indexes on same line. - (while (and (<= 0 (setq i (1- i))) - (<= start-of-line (aref edebug-points i)))) - ;; Insert all the indices for this line. - (forward-line 1) - (setq start-of-count-line (point) - first-index i ; really last index for line above this one. - last-count -1) ; cause first count to always appear. - (insert ";#") - ;; i == first-index still - (while (<= (setq i (1+ i)) last-index) - (let ((count (aref counts i)) - (coverage (aref coverages i)) - (col (save-excursion - (goto-char (+ (aref edebug-points i) def-mark)) - (- (current-column) - (if (= ?\( (following-char)) 0 1))))) - (insert (make-string - (max 0 (- col (- (point) start-of-count-line))) ?\ ) - (if (and (< 0 count) - (not (memq coverage - '(unknown ok-coverage)))) - "=" "") - (if (= count last-count) "" (int-to-string count)) - " ") - (setq last-count count))) - (insert "\n") - (setq i first-index))))) - -(defun edebug-temp-display-freq-count () - "Temporarily display the frequency count data for the current definition. -It is removed when you hit any char." - ;; This seems not to work with Emacs 18.59. It undoes too far. - (interactive) - (let ((buffer-read-only nil)) - (undo-boundary) - (edebug-display-freq-count) - (setq unread-command-char (read-char)) - (undo))) - - -;;; Menus - -(defun edebug-toggle (variable) - (set variable (not (eval variable))) - (message "%s: %s" variable (eval variable))) - -;; We have to require easymenu (even for Emacs 18) just so -;; the easy-menu-define macro call is compiled correctly. -(require 'easymenu) - -(defconst edebug-mode-menus - '("Edebug" - "----" - ["Stop" edebug-stop t] - ["Step" edebug-step-mode t] - ["Next" edebug-next-mode t] - ["Trace" edebug-trace-mode t] - ["Trace Fast" edebug-Trace-fast-mode t] - ["Continue" edebug-continue-mode t] - ["Continue Fast" edebug-Continue-fast-mode t] - ["Go" edebug-go-mode t] - ["Go Nonstop" edebug-Go-nonstop-mode t] - "----" - ["Help" edebug-help t] - ["Abort" abort-recursive-edit t] - ["Quit to Top Level" top-level t] - ["Quit Nonstop" edebug-top-level-nonstop t] - "----" - ("Jumps" - ["Forward Sexp" edebug-forward-sexp t] - ["Step In" edebug-step-in t] - ["Step Out" edebug-step-out t] - ["Goto Here" edebug-goto-here t]) - - ("Breaks" - ["Set Breakpoint" edebug-set-breakpoint t] - ["Unset Breakpoint" edebug-unset-breakpoint t] - ["Set Conditional Breakpoint" edebug-set-conditional-breakpoint t] - ["Set Global Break Condition" edebug-set-global-break-condition t] - ["Show Next Breakpoint" edebug-next-breakpoint t]) - - ("Views" - ["Where am I?" edebug-where t] - ["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] - ["Display Freq Count" edebug-display-freq-count t]) - - ("Eval" - ["Expression" edebug-eval-expression t] - ["Last Sexp" edebug-eval-last-sexp t] - ["Visit Eval List" edebug-visit-eval-list t]) - - ("Options" - ["Edebug All Defs" edebug-all-defs t] - ["Edebug All Forms" edebug-all-forms t] - "----" - ["Toggle Tracing" (edebug-toggle 'edebug-trace) t] - ["Toggle Coverage Testing" (edebug-toggle 'edebug-test-coverage) t] - ["Toggle Window Saving" edebug-toggle-save-windows t] - ["Toggle Point Saving" - (edebug-toggle 'edebug-save-displayed-buffer-points) t] - )) - "XEmacs style menus for Edebug.") - - -;;; Emacs version specific code - -;;; The default for all above is Emacs 18, because it is easier to compile -;;; Emacs 18 code in Emacs 19 than vice versa. This default will -;;; change once most people are using Emacs 19 or derivatives. - -;; Epoch specific code is in a separate file: edebug-epoch.el. - -;; The byte-compiler will complain about changes in number of arguments -;; to functions like mark and read-from-minibuffer. These warnings -;; may be ignored because the right call should always be made. - -(defun edebug-emacs-19-specific () - - (defalias 'edebug-window-live-p 'window-live-p) - - ;; Mark takes an argument in Emacs 19. - (defun edebug-mark () - (mark t));; Does this work for XEmacs too? - - ;; Use minibuffer-history when reading expressions. - (defvar read-expression-history) ;; hush bytecomp - (defvar read-expression-map) - - (defun edebug-set-conditional-breakpoint (arg condition) - "Set a conditional breakpoint at nearest sexp. -The condition is evaluated in the outside context. -With prefix argument, make it a temporary breakpoint." - ;; (interactive "P\nxCondition: ") - (interactive - (list - current-prefix-arg - ;; Read condition as follows; getting previous condition is cumbersome: - (let ((edebug-stop-point (edebug-find-stop-point))) - (if edebug-stop-point - (let* ((edebug-def-name (car edebug-stop-point)) - (index (cdr edebug-stop-point)) - (edebug-data (get edebug-def-name 'edebug)) - (edebug-breakpoints (car (cdr edebug-data))) - (edebug-break-data (assq index edebug-breakpoints)) - (edebug-break-condition (car (cdr edebug-break-data))) - (edebug-expression-history - ;; Prepend the current condition, if any. - (if edebug-break-condition - (cons edebug-break-condition read-expression-history) - read-expression-history))) - (prog1 - (read-from-minibuffer - "Condition: " nil read-expression-map t - 'edebug-expression-history) - (setq read-expression-history edebug-expression-history) - )))))) - (edebug-modify-breakpoint t condition arg)) - - (defun edebug-eval-expression (edebug-expr) - "Evaluate an expression in the outside environment. -If interactive, prompt for the expression. -Print result in minibuffer." - (interactive (list (read-from-minibuffer - "Eval: " nil read-expression-map t - 'read-expression-history))) - (princ - (edebug-outside-excursion - (setq values (cons (edebug-eval edebug-expr) values)) - (edebug-safe-prin1-to-string (car values))))) - - (easy-menu-define edebug-menu edebug-mode-map "Edebug menus" edebug-mode-menus) - (if (eq (console-type) 'x) ; XEmacs - (x-popup-menu nil (lookup-key edebug-mode-map [menu-bar Edebug]))) - ) - - -(defun edebug-xemacs-specific () - - ;; We need to bind zmacs-regions to nil around all calls to `mark' and - ;; `mark-marker' but don't bind it to nil before entering a recursive edit, - ;; that is, don't interfere with the binding the user might see while - ;; executing a command. - - (defvar zmacs-regions) - - (defun edebug-mark () - (let ((zmacs-regions nil)) - (mark))) - - (defun edebug-mark-marker () - (let ((zmacs-regions nil));; for XEmacs - (mark-marker))) - - - (defun edebug-mode-menu (event) - (interactive "@event") - (popup-menu edebug-mode-menus)) - - (define-key edebug-mode-map 'button3 'edebug-mode-menu) - ) - -(defun edebug-emacs-version-specific () - (cond - ((string-match "XEmacs" emacs-version);; XEmacs - (edebug-xemacs-specific)) - - ((and (boundp 'epoch::version) epoch::version) - (require 'edebug-epoch)) - - ((not (string-match "^18" emacs-version)) - (edebug-emacs-19-specific)))) - -(edebug-emacs-version-specific) - - -;;; Byte-compiler - -;; Extension for bytecomp to resolve undefined function references. -;; Requires new byte compiler. - -;; Reenable byte compiler warnings about unread-command-char and -event. -;; Disabled before edebug-recursive-edit. -(eval-when-compile - (if edebug-unread-command-char-warning - (put 'unread-command-char 'byte-obsolete-variable - edebug-unread-command-char-warning)) - (if edebug-unread-command-event-warning - (put 'unread-command-event 'byte-obsolete-variable - edebug-unread-command-event-warning))) - -(eval-when-compile - ;; The body of eval-when-compile seems to get evaluated with eval-defun. - ;; We only want to evaluate when actually byte compiling. - ;; But it is OK to evaluate as long as byte-compiler has been loaded. - (if (featurep 'byte-compile) (progn - - (defun byte-compile-resolve-functions (funcs) - "Say it is OK for the named functions to be unresolved." - (mapcar - (function - (lambda (func) - (setq byte-compile-unresolved-functions - (delq (assq func byte-compile-unresolved-functions) - byte-compile-unresolved-functions)))) - funcs) - nil) - - '(defun byte-compile-resolve-free-references (vars) - "Say it is OK for the named variables to be referenced." - (mapcar - (function - (lambda (var) - (setq byte-compile-free-references - (delq var byte-compile-free-references)))) - vars) - nil) - - '(defun byte-compile-resolve-free-assignments (vars) - "Say it is OK for the named variables to be assigned." - (mapcar - (function - (lambda (var) - (setq byte-compile-free-assignments - (delq var byte-compile-free-assignments)))) - vars) - nil) - - (byte-compile-resolve-functions - '(reporter-submit-bug-report - edebug-gensym ;; also in cl.el - ;; Interfaces to standard functions. - edebug-original-eval-defun - edebug-original-read - edebug-get-buffer-window - edebug-mark - edebug-mark-marker - edebug-input-pending-p - edebug-sit-for - edebug-prin1-to-string - edebug-format - edebug-original-signal - ;; XEmacs - zmacs-deactivate-region - popup-menu - ;; CL - cl-macroexpand-all - ;; And believe it or not, the byte compiler doesn't know about: - byte-compile-resolve-functions - )) - - '(byte-compile-resolve-free-references - '(read-expression-history - read-expression-map)) - - '(byte-compile-resolve-free-assignments - '(read-expression-history)) - - ))) - - -;;; Autoloading of Edebug accessories - -(if (featurep 'cl) - (add-hook 'edebug-setup-hook - (function (lambda () (require 'cl-specs)))) - ;; The following causes cl-specs to be loaded if you load cl.el. - (add-hook 'cl-load-hook - (function (lambda () (require 'cl-specs))))) - -;;; edebug-cl-read and cl-read are available from liberte@cs.uiuc.edu -(if (featurep 'cl-read) - (add-hook 'edebug-setup-hook - (function (lambda () (require 'edebug-cl-read)))) - ;; The following causes edebug-cl-read to be loaded when you load cl-read.el. - (add-hook 'cl-read-load-hooks - (function (lambda () (require 'edebug-cl-read))))) - - -;;; Finalize Loading - -;;; Finally, hook edebug into the rest of Emacs. -;;; There are probably some other things that could go here. - -;; Install edebug read and eval functions. -(edebug-install-read-eval-functions) - -(provide 'edebug) - -;;; edebug.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/edebug/eval-reg.el --- a/lisp/edebug/eval-reg.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ -;;; eval-reg.el --- Redefine eval-region, and subrs that use it, in Lisp - -;; Copyright (C) 1994 Daniel LaLiberte - -;; Author: Daniel LaLiberte -;; Keywords: lisp - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: Not in FSF - -;;; Commentary: - -;; eval-region, eval-buffer, and eval-current-buffer are redefined in -;; Lisp to allow customizations by Lisp code. eval-region calls -;; `read', `eval', and `prin1', so Lisp replacements of these -;; functions will affect eval-region and anything else that calls it. -;; eval-buffer and eval-current-buffer are redefined in Lisp to call -;; eval-region on the buffer. - -;; Because of dynamic binding, all local variables are protected from -;; being seen by eval by giving them funky names. But variables in -;; routines that call eval-region are similarly exposed. - -;; Perhaps this should be one of several files in an `elisp' package -;; that replaces Emacs Lisp subroutines with Lisp versions of the -;; same. - -;; Eval-region may be installed, after loading, by calling: -;; (elisp-eval-region-install). Installation can be undone with: -;; (elisp-eval-region-uninstall). - -;;; Code: - -'(defpackage "elisp-eval-region" - (:nicknames "elisp") - (:use "elisp") - (:export - elisp-eval-region-install - elisp-eval-region-uninstall - elisp-eval-region-level - with-elisp-eval-region - eval-region - eval-buffer - eval-current-buffer - )) -'(in-package elisp-eval-region) - -;; Save standard versions. -(if (not (fboundp 'original-eval-region)) - (defalias 'original-eval-region (symbol-function 'eval-region))) -(if (not (fboundp 'original-eval-buffer)) - (defalias 'original-eval-buffer - (if (fboundp 'eval-buffer) ;; only in Emacs 19 - (symbol-function 'eval-buffer) - 'undefined))) -(if (not (fboundp 'original-eval-current-buffer)) - (defalias 'original-eval-current-buffer - (symbol-function 'eval-current-buffer))) - -(defvar elisp-eval-region-level 0 - "If the value is 0, use the original version of `elisp-eval-region'. -Callers of `elisp-eval-region' should increment `elisp-eval-region-level' -while the Lisp version should be used. Installing `elisp-eval-region' -increments it once, and uninstalling decrements it.") - -;; Installing and uninstalling should always be used in pairs, -;; or just install once and never uninstall. -(defun elisp-eval-region-install () - (interactive) - (defalias 'eval-region 'elisp-eval-region) - (defalias 'eval-buffer 'elisp-eval-buffer) - (defalias 'eval-current-buffer 'elisp-eval-current-buffer) - (setq elisp-eval-region-level (1+ elisp-eval-region-level))) - -(defun elisp-eval-region-uninstall () - (interactive) - (if (> 1 elisp-eval-region-level) - (setq elisp-eval-region-level (1- elisp-eval-region-level)) - (setq elisp-eval-region-level 0) - (defalias 'eval-region (symbol-function 'original-eval-region)) - (defalias 'eval-buffer (symbol-function 'original-eval-buffer)) - (defalias 'eval-current-buffer - (symbol-function 'original-eval-current-buffer)) - )) - -(put 'with-elisp-eval-region 'lisp-indent-function 1) -(put 'with-elisp-eval-region 'lisp-indent-hook 1) -(put 'with-elisp-eval-region 'edebug-form-spec t) - -(defmacro with-elisp-eval-region (flag &rest body) - "If FLAG is nil, decrement `eval-region-level' while executing BODY. -The effect of decrementing all the way to zero is that `eval-region' -will use the original `eval-region', which may be the Emacs subr or some -previous redefinition. Before calling this macro, this package should -already have been installed, using `elisp-eval-region-install', which -increments the count once. So if another package still requires the -Lisp version of the code, the count will still be non-zero. - -The count is not bound locally by this macro, so changes by BODY to -its value will not be lost." - (` (let ((elisp-code (function (lambda () (,@ body))))) - (if (not (, flag)) - (unwind-protect - (progn - (setq elisp-eval-region-level (1- elisp-eval-region-level)) - (funcall elisp-code)) - (setq elisp-eval-region-level (1+ elisp-eval-region-level))) - (funcall elisp-code))))) - - -(defun elisp-eval-region (elisp-start elisp-end &optional elisp-output) - "Execute the region as Lisp code. -When called from programs, expects two arguments, -giving starting and ending indices in the current buffer -of the text to be executed. -Programs can pass third argument PRINTFLAG which controls printing of output: -nil means discard it; anything else is stream for print. - -This version, from `eval-reg.el', allows Lisp customization of read, -eval, and the printer." - - ;; Because this doesnt narrow to the region, one other difference - ;; concerns inserting whitespace after the expression being evaluated. - - (interactive "r") - (if (= 0 elisp-eval-region-level) - (original-eval-region elisp-start elisp-end elisp-output) - (let ((elisp-pnt (point)) - (elisp-buf (current-buffer));; Outside buffer - (elisp-inside-buf (current-buffer));; Buffer current while evaling - ;; Mark the end because it may move. - (elisp-end-marker (set-marker (make-marker) elisp-end)) - elisp-form - elisp-val) - (goto-char elisp-start) - (elisp-skip-whitespace) - (while (< (point) elisp-end-marker) - (setq elisp-form (read elisp-buf)) - - (let ((elisp-current-buffer (current-buffer))) - ;; Restore the inside current-buffer. - (set-buffer elisp-inside-buf) - (setq elisp-val (eval elisp-form)) - ;; Remember current buffer for next time. - (setq elisp-inside-buf (current-buffer)) - ;; Should this be protected? - (set-buffer elisp-current-buffer)) - - (if elisp-output - (let ((standard-output (or elisp-output t))) - (setq values (cons elisp-val values)) - (if (eq standard-output t) - (prin1 elisp-val) - (princ "\n") - (prin1 elisp-val) - (princ "\n") - ))) - (goto-char (min (max elisp-end-marker (point)) - (progn (elisp-skip-whitespace) (point)))) - ) ; while - (if elisp-output nil - ;; like save-excursion recovery, but done only if no error occurs - ;; but mark is not restored - (set-buffer elisp-buf) - (goto-char elisp-pnt)) - nil))) - - -(defun elisp-skip-whitespace () - ;; Leave point before the next token, skipping white space and comments. - (skip-chars-forward " \t\r\n\f") - (while (= (following-char) ?\;) - (skip-chars-forward "^\n\r") ; skip the comment - (skip-chars-forward " \t\r\n\f"))) - - -(defun elisp-eval-current-buffer (&optional elisp-output) - "Execute the current buffer as Lisp code. -Programs can pass argument PRINTFLAG which controls printing of output: -nil means discard it; anything else is stream for print. - -This version calls `eval-region' on the whole buffer." - ;; The standard eval-current-buffer doesn't use eval-region. - (interactive) - (eval-region (point-min) (point-max) elisp-output)) - - -(defun elisp-eval-buffer (&optional elisp-bufname elisp-printflag) - "Execute BUFFER as Lisp code. Use current buffer if BUFFER is nil. -Programs can pass argument PRINTFLAG which controls printing of -output: nil means discard it; anything else is stream for print. - -This version calls `eval-region' on the whole buffer." - (interactive) - (if (null elisp-bufname) - (setq elisp-bufname (current-buffer))) - (save-excursion - (set-buffer (or (get-buffer elisp-bufname) - (error "No such buffer: %s" elisp-bufname))) - (eval-region (point-min) (point-max) elisp-printflag))) - -(provide 'eval-reg) - -;;; eval-reg.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/electric/auto-autoloads.el --- a/lisp/electric/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'electric-autoloads) (error "Already loaded")) - -;;;### (autoloads (electric-buffer-list) "ebuff-menu" "electric/ebuff-menu.el") - -(autoload 'electric-buffer-list "ebuff-menu" "\ -Pops up a buffer describing the set of Emacs buffers. -Vaguely like ITS lunar select buffer; combining typeoutoid buffer -listing with menuoid buffer selection. - -If the very next character typed is a space then the buffer list -window disappears. Otherwise, one may move around in the buffer list -window, marking buffers to be selected, saved or deleted. - -To exit and select a new buffer, type a space when the cursor is on -the appropriate line of the buffer-list window. Other commands are -much like those of buffer-menu-mode. - -Calls value of `electric-buffer-menu-mode-hook' on entry if non-nil. - -Non-null optional arg FILES-ONLY means mention only file buffers. -When called from Lisp code, FILES-ONLY may be a regular expression, -in which case only buffers whose names match that expression are listed, -or an arbitrary predicate function. - -\\{electric-buffer-menu-mode-map}" t nil) - -;;;*** - -;;;### (autoloads (electric-command-history Electric-command-history-redo-expression) "echistory" "electric/echistory.el") - -(autoload 'Electric-command-history-redo-expression "echistory" "\ -Edit current history line in minibuffer and execute result. -With prefix arg NOCONFIRM, execute current line as-is without editing." t nil) - -(autoload 'electric-command-history "echistory" "\ -\\Major mode for examining and redoing commands from `command-history'. -This pops up a window with the Command History listing. -The number of command listed is controlled by `list-command-history-max'. -The command history is filtered by `list-command-history-filter' if non-nil. -Combines typeout Command History list window with menu like selection -of an expression from the history for re-evaluation in the *original* buffer. - -The history displayed is filtered by `list-command-history-filter' if non-nil. - -Like Emacs-Lisp mode except that characters do not insert themselves and -Tab and Linefeed do not indent. Instead these commands are provided: -\\{electric-history-map} - -Calls the value of `electric-command-history-hook' if that is non-nil. -The Command History listing is recomputed each time this mode is invoked." t nil) - -;;;*** - -;;;### (autoloads (electric-helpify with-electric-help) "ehelp" "electric/ehelp.el") - -(autoload 'with-electric-help "ehelp" "\ -Pop up an \"electric\" help buffer. -The arguments are THUNK &optional BUFFER NOERASE MINHEIGHT. -THUNK is a function of no arguments which is called to initialize the -contents of BUFFER. BUFFER defaults to `*Help*'. BUFFER will be -erased before THUNK is called unless NOERASE is non-nil. THUNK will -be called while BUFFER is current and with `standard-output' bound to -the buffer specified by BUFFER. - -If THUNK returns nil, we display BUFFER starting at the top, and -shrink the window to fit. If THUNK returns non-nil, we don't do those things. - -After THUNK has been called, this function \"electrically\" pops up a window -in which BUFFER is displayed and allows the user to scroll through that buffer -in electric-help-mode. The window's height will be at least MINHEIGHT if -this value is non-nil. - -If THUNK returns nil, we display BUFFER starting at the top, and -shrink the window to fit. If THUNK returns non-nil, we don't do those -things. - -When the user exits (with `electric-help-exit', or otherwise) the help -buffer's window disappears (i.e., we use `save-window-excursion') -BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit." nil nil) - -(autoload 'electric-helpify "ehelp" nil nil nil) - -;;;*** - -;;;### (autoloads (Helper-help Helper-describe-bindings) "helper" "electric/helper.el") - -(autoload 'Helper-describe-bindings "helper" "\ -Describe local key bindings of current mode." t nil) - -(autoload 'Helper-help "helper" "\ -Provide help for current mode." t nil) - -;;;*** - -(provide 'electric-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/electric/ebuff-menu.el --- a/lisp/electric/ebuff-menu.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,302 +0,0 @@ -;;; ebuff-menu.el --- electric-buffer-list mode - -;; Copyright (C) 1985, 1986, 1994 Free Software Foundation, Inc. - -;; Author: Richard Mlynarik -;; Keywords: frames - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; Who says one can't have typeout windows in GNU Emacs? The entry -;; point, `electric-buffer-list' works like ^r select buffer from the -;; ITS Emacs lunar or tmacs libraries. - -;;; Code: - -(require 'electric) -;; XEmacs change -(require 'buff-menu) - -;; this depends on the format of list-buffers (from src/buffer.c) and -;; on stuff in lisp/buff-menu.el - -(defvar electric-buffer-menu-mode-map nil) - -;;;###autoload -(defun electric-buffer-list (&optional files-only) - "Pops up a buffer describing the set of Emacs buffers. -Vaguely like ITS lunar select buffer; combining typeoutoid buffer -listing with menuoid buffer selection. - -If the very next character typed is a space then the buffer list -window disappears. Otherwise, one may move around in the buffer list -window, marking buffers to be selected, saved or deleted. - -To exit and select a new buffer, type a space when the cursor is on -the appropriate line of the buffer-list window. Other commands are -much like those of buffer-menu-mode. - -Calls value of `electric-buffer-menu-mode-hook' on entry if non-nil. - -Non-null optional arg FILES-ONLY means mention only file buffers. -When called from Lisp code, FILES-ONLY may be a regular expression, -in which case only buffers whose names match that expression are listed, -or an arbitrary predicate function. - -\\{electric-buffer-menu-mode-map}" - (interactive (list (if current-prefix-arg t nil))) - (let (select buffer) - (save-window-excursion - (save-window-excursion (list-buffers files-only)) - (setq buffer (window-buffer (Electric-pop-up-window "*Buffer List*"))) - (unwind-protect - (progn - (set-buffer buffer) - (Electric-buffer-menu-mode) - (setq select - (catch 'electric-buffer-menu-select - (message "<<< Press Return to bury the buffer list >>>") - ;; XEmacs change - (if (eq (setq unread-command-events - (list (next-command-event))) - ?\ ) - (progn (setq unread-command-events nil) - (throw 'electric-buffer-menu-select nil))) - (let ((start-point (point)) - (first (progn (goto-char (point-min)) - (forward-line 2) - (point))) - (last (progn (goto-char (point-max)) - (forward-line -1) - (point))) - (goal-column 0)) - ;; Use start-point if it is meaningful. - (goto-char (if (or (< start-point first) - (> start-point last)) - first - start-point)) - (Electric-command-loop 'electric-buffer-menu-select - nil - t - 'electric-buffer-menu-looper - (cons first last)))))) - (set-buffer buffer) - (Buffer-menu-mode) - (bury-buffer buffer) - (message ""))) - (if select - (progn (set-buffer buffer) - (let ((opoint (point-marker))) - (Buffer-menu-execute) - (goto-char (point-min)) - (if (prog1 (search-forward "\n>" nil t) - (goto-char opoint) (set-marker opoint nil)) - (Buffer-menu-select) - (switch-to-buffer (Buffer-menu-buffer t)))))))) - -(defun electric-buffer-menu-looper (state condition) - (cond ((and condition - (not (memq (car condition) '(buffer-read-only - end-of-buffer - beginning-of-buffer)))) - (signal (car condition) (cdr condition))) - ((< (point) (car state)) - (goto-char (point-min)) - (forward-line 2)) - ((> (point) (cdr state)) - (goto-char (point-max)) - (forward-line -1) - (if (pos-visible-in-window-p (point-max)) - (recenter -1))))) - -(put 'Electric-buffer-menu-mode 'mode-class 'special) -(defun Electric-buffer-menu-mode () - "Major mode for editing a list of buffers. -Each line describes one of the buffers in Emacs. -Letters do not insert themselves; instead, they are commands. -\\ -\\[keyboard-quit] or \\[Electric-buffer-menu-quit] -- exit buffer menu, returning to previous window and buffer - configuration. If the very first character typed is a space, it - also has this effect. -\\[Electric-buffer-menu-select] -- select buffer of line point is on. - Also show buffers marked with m in other windows, - deletes buffers marked with \"D\", and saves those marked with \"S\". -\\[Buffer-menu-mark] -- mark buffer to be displayed. -\\[Buffer-menu-not-modified] -- clear modified-flag on that buffer. -\\[Buffer-menu-save] -- mark that buffer to be saved. -\\[Buffer-menu-delete] or \\[Buffer-menu-delete-backwards] -- mark that buffer to be deleted. -\\[Buffer-menu-unmark] -- remove all kinds of marks from current line. -\\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done. -\\[Buffer-menu-backup-unmark] -- back up a line and remove marks. - -\\{electric-buffer-menu-mode-map} - -Entry to this mode via command `electric-buffer-list' calls the value of -`electric-buffer-menu-mode-hook' if it is non-nil." - (kill-all-local-variables) - (use-local-map electric-buffer-menu-mode-map) - (setq mode-name "Electric Buffer Menu") - (setq mode-line-buffer-identification "Electric Buffer List") - ;; XEmacs - (if (memq 'mode-name mode-line-format) - (progn (setq mode-line-format (copy-sequence mode-line-format)) - (setcar (memq 'mode-name mode-line-format) "Buffers"))) - (make-local-variable 'Helper-return-blurb) - (setq Helper-return-blurb "return to buffer editing") - (setq truncate-lines t) - ;; XEmacs - (setq buffer-scrollbar-height 0) - (setq buffer-read-only t) - (setq major-mode 'Electric-buffer-menu-mode) - ;; XEmacs - (setq mode-motion-hook 'mode-motion-highlight-line) - (goto-char (point-min)) - (if (search-forward "\n." nil t) (forward-char -1)) - (run-hooks 'electric-buffer-menu-mode-hook)) - -;; generally the same as Buffer-menu-mode-map -;; (except we don't indirect to global-map) -(put 'Electric-buffer-menu-undefined 'suppress-keymap t) -(if electric-buffer-menu-mode-map - nil - (let ((map (make-keymap)) (submap (make-keymap))) - ;(fillarray (car (cdr map)) 'Electric-buffer-menu-undefined) ; FSF - (let ((i 0)) - (while (< i 128) - (define-key map (make-string 1 i) 'Electric-buffer-menu-undefined) - (setq i (1+ i)))) - (define-key map "\e" submap) - ;(fillarray (car (cdr submap)) 'Electric-buffer-menu-undefined) ; FSF - (let ((map2 (lookup-key map "\e")) - (i 0)) - (while (< i 128) - (define-key map2 (make-string 1 i) 'Electric-buffer-menu-undefined) - (setq i (1+ i)))) - (define-key map "\C-z" 'suspend-emacs) - (define-key map "v" 'Electric-buffer-menu-mode-view-buffer) - (define-key map (vector help-char) 'Helper-help) - (define-key map "?" 'Helper-describe-bindings) - (define-key map "\C-c" nil) - (define-key map "\C-c\C-c" 'Electric-buffer-menu-quit) - (define-key map "\C-]" 'Electric-buffer-menu-quit) - (define-key map "q" 'Electric-buffer-menu-quit) - (define-key map " " 'Electric-buffer-menu-select) - (define-key map "\C-m" 'Electric-buffer-menu-select) - (define-key map "\C-l" 'recenter) - (define-key map "s" 'Buffer-menu-save) - (define-key map "d" 'Buffer-menu-delete) - (define-key map "k" 'Buffer-menu-delete) - (define-key map "\C-d" 'Buffer-menu-delete-backwards) - ;(define-key map "\C-k" 'Buffer-menu-delete) - (define-key map "\177" 'Buffer-menu-backup-unmark) - ;; XEmacs - (define-key map 'backspace 'Buffer-menu-backup-unmark) - (define-key map "~" 'Buffer-menu-not-modified) - (define-key map "u" 'Buffer-menu-unmark) - (let ((i ?0)) - (while (<= i ?9) - (define-key map (char-to-string i) 'digit-argument) - ;;#### Urk! - (define-key map (concat "\e" (char-to-string i)) 'digit-argument) - (setq i (1+ i)))) - (define-key map "-" 'negative-argument) - (define-key map "\e-" 'negative-argument) - (define-key map "m" 'Buffer-menu-mark) - (define-key map "\C-u" 'universal-argument) - (define-key map "\C-p" 'previous-line) - (define-key map "\C-n" 'next-line) - (define-key map "p" 'previous-line) - (define-key map "n" 'next-line) - (define-key map "\C-v" 'scroll-up) - (define-key map "\ev" 'scroll-down) - (define-key map ">" 'scroll-right) - (define-key map "<" 'scroll-left) - (define-key map "\e\C-v" 'scroll-other-window) - (define-key map "\e>" 'end-of-buffer) - (define-key map "\e<" 'beginning-of-buffer) - (define-key map "\e\e" nil) - (define-key map "\e\e\e" 'Electric-buffer-menu-quit) - ;; XEmacs - (define-key map [home] 'beginning-of-buffer) - (define-key map [down] 'next-line) - (define-key map [up] 'previous-line) - (define-key map [prior] 'scroll-down) - (define-key map [next] 'scroll-up) - (define-key map 'button2 'Electric-buffer-menu-mouse-select) - (define-key map 'button3 'Buffer-menu-popup-menu) - (setq electric-buffer-menu-mode-map map))) - -(defun Electric-buffer-menu-exit () - (interactive) - ;; XEmacs - (setq unread-command-event last-input-event) - ;; for robustness - (condition-case () - (throw 'electric-buffer-menu-select nil) - (error (Buffer-menu-mode) - (other-buffer)))) - -(defun Electric-buffer-menu-select () - "Leave Electric Buffer Menu, selecting buffers and executing changes. -Saves buffers marked \"S\". Deletes buffers marked \"K\". -Selects buffer at point and displays buffers marked \">\" in other windows." - (interactive) - (throw 'electric-buffer-menu-select (point))) - -(defun Electric-buffer-menu-mouse-select (event) - (interactive "e") - ;; XEmacs is simpler - (mouse-set-point event) - (Electric-buffer-menu-select)) - -(defun Electric-buffer-menu-quit () - "Leave Electric Buffer Menu, restoring previous window configuration. -Does not execute select, save, or delete commands." - (interactive) - (throw 'electric-buffer-menu-select nil)) - -(defun Electric-buffer-menu-undefined () - (interactive) - (ding) - (message "%s" - (if (and (eq (key-binding "\C-c\C-c") 'Electric-buffer-menu-quit) - (eq (key-binding " ") 'Electric-buffer-menu-select) - (eq (key-binding (vector help-char)) 'Helper-help) - (eq (key-binding "?") 'Helper-describe-bindings)) - (substitute-command-keys "Type C-c C-c to exit, Space to select, -Type \\[Electric-buffer-menu-quit] to exit, \ -\\[Electric-buffer-menu-select] to select, \ -\\[Helper-help] for help, \\[Helper-describe-bindings] for commands."))) - (sit-for 4)) - -(defun Electric-buffer-menu-mode-view-buffer () - "View buffer on current line in Electric Buffer Menu. -Returns to Electric Buffer Menu when done." - (interactive) - (let ((bufnam (Buffer-menu-buffer nil))) - (if bufnam - (view-buffer bufnam) - (ding) - (message "Buffer %s does not exist!" bufnam) - (sit-for 4)))) - -;;; ebuff-menu.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/electric/echistory.el --- a/lisp/electric/echistory.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -;;; echistory.el --- Electric Command History Mode - -;; Copyright (C) 1985 Free Software Foundation, Inc. - -;; Author: K. Shane Hartman -;; Maintainer: FSF -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Code: - -(require 'electric) ; command loop -(require 'chistory) ; history lister - -;;;###autoload -(defun Electric-command-history-redo-expression (&optional noconfirm) - "Edit current history line in minibuffer and execute result. -With prefix arg NOCONFIRM, execute current line as-is without editing." - (interactive "P") - (let (todo) - (save-excursion - (set-buffer "*Command History*") - (beginning-of-line) - (setq todo (read (current-buffer))) - (if (boundp 'electric-history-in-progress) - (if todo (throw 'electric-history-quit (list noconfirm todo))))))) - -(defvar electric-history-map ()) -(if electric-history-map - () - ;; XEmacs - (setq electric-history-map (make-keymap)) - (set-keymap-name electric-history-map 'electric-history-map) - (set-keymap-default-binding electric-history-map 'Electric-history-undefined) - (define-key electric-history-map "\C-u" 'universal-argument) - (define-key electric-history-map " " 'Electric-command-history-redo-expression) - (define-key electric-history-map "!" 'Electric-command-history-redo-expression) - (define-key electric-history-map "\e\C-x" 'eval-sexp) - (define-key electric-history-map "\e\C-d" 'down-list) - (define-key electric-history-map "\e\C-u" 'backward-up-list) - (define-key electric-history-map "\e\C-b" 'backward-sexp) - (define-key electric-history-map "\e\C-f" 'forward-sexp) - (define-key electric-history-map "\e\C-a" 'beginning-of-defun) - (define-key electric-history-map "\e\C-e" 'end-of-defun) - (define-key electric-history-map "\e\C-n" 'forward-list) - (define-key electric-history-map "\e\C-p" 'backward-list) - (define-key electric-history-map "q" 'Electric-history-quit) - (define-key electric-history-map "\C-c" nil) - (define-key electric-history-map "\C-c\C-c" 'Electric-history-quit) - (define-key electric-history-map "\C-]" 'Electric-history-quit) - (define-key electric-history-map "\C-z" 'suspend-emacs) - (define-key electric-history-map (vector help-char) 'Helper-help) - ;; XEmacs - (define-key electric-history-map 'backspace 'previous-line) - (define-key electric-history-map "?" 'Helper-describe-bindings) - (define-key electric-history-map "\e>" 'end-of-buffer) - (define-key electric-history-map "\e<" 'beginning-of-buffer) - (define-key electric-history-map "\n" 'next-line) - (define-key electric-history-map "\r" 'next-line) - (define-key electric-history-map "\177" 'previous-line) - (define-key electric-history-map "\C-n" 'next-line) - (define-key electric-history-map "\C-p" 'previous-line) - (define-key electric-history-map "\ev" 'scroll-down) - (define-key electric-history-map "\C-v" 'scroll-up) - (define-key electric-history-map [home] 'beginning-of-buffer) - (define-key electric-history-map [down] 'next-line) - (define-key electric-history-map [up] 'previous-line) - (define-key electric-history-map [prior] 'scroll-down) - (define-key electric-history-map [next] 'scroll-up) - (define-key electric-history-map "\C-l" 'recenter) - (define-key electric-history-map "\e\C-v" 'scroll-other-window)) - -(defvar electric-command-history-hook nil - "If non-nil, its value is called by `electric-command-history'.") - -;;;###autoload -(defun electric-command-history () - "\\Major mode for examining and redoing commands from `command-history'. -This pops up a window with the Command History listing. -The number of command listed is controlled by `list-command-history-max'. -The command history is filtered by `list-command-history-filter' if non-nil. -Combines typeout Command History list window with menu like selection -of an expression from the history for re-evaluation in the *original* buffer. - -The history displayed is filtered by `list-command-history-filter' if non-nil. - -Like Emacs-Lisp mode except that characters do not insert themselves and -Tab and Linefeed do not indent. Instead these commands are provided: -\\{electric-history-map} - -Calls the value of `electric-command-history-hook' if that is non-nil. -The Command History listing is recomputed each time this mode is invoked." - (interactive) - (let ((electric-history-in-progress t) - (old-buffer (current-buffer)) - (todo)) - (unwind-protect - (setq todo - (catch 'electric-history-quit - (save-window-excursion - (save-window-excursion - (list-command-history) - (set-buffer "*Command History*") - (Command-history-setup 'electric-command-history - "Electric History" - electric-history-map)) - (Electric-pop-up-window "*Command History*") - (run-hooks 'electric-command-history-hook) - (if (eobp) - (progn (ding) - (message "No command history.") - (throw 'electric-history-quit nil)) - (let ((Helper-return-blurb "return to History")) - (Electric-command-loop 'electric-history-quit - "->" t)))))) - (set-buffer "*Command History*") - (Command-history-setup) - (bury-buffer (current-buffer))) - (if (consp todo) - (progn (set-buffer old-buffer) - (if (car todo) - (apply (car (car (cdr todo))) (cdr (car (cdr todo)))) - (edit-and-eval-command "Redo: " (car (cdr todo)))))))) - -(defun Electric-history-undefined () - (interactive) - (ding) - (message (substitute-command-keys "Type \\[Helper-help] for help, ? for commands, C-c C-c to quit, Space to execute")) - (sit-for 4)) - -(defun Electric-history-quit () - "Quit Electric Command History, restoring previous window configuration." - (interactive) - (if (boundp 'electric-history-in-progress) - (progn (message "") - (throw 'electric-history-quit nil)))) - -;;; echistory.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/electric/ehelp.el --- a/lisp/electric/ehelp.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,418 +0,0 @@ -;;; ehelp.el --- bindings for electric-help mode - -;; Copyright (C) 1986, 1995 Free Software Foundation, Inc. - -;; Author: Richard Mlynarik -;; Maintainer: FSF -;; Keywords: help, extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -;; This package provides a pre-packaged `Electric Help Mode' for -;; browsing on-line help screens. There is one entry point, -;; `with-electric-help'; all you have to give it is a no-argument -;; function that generates the actual text of the help into the current -;; buffer. - -;; To make this the default, you must do -;; (require 'ehelp) -;; (define-key global-map "\C-h" 'ehelp-command) -;; (define-key global-map [help] 'ehelp-command) -;; (define-key global-map [f1] 'ehelp-command) - -;;; Code: - -(require 'electric) -(defvar electric-help-map () - "Keymap defining commands available in `electric-help-mode'.") - -(defvar electric-help-form-to-execute nil) - -(put 'electric-help-undefined 'suppress-keymap t) -(if electric-help-map - () - (let ((map (make-keymap))) - ;; allow all non-self-inserting keys - search, scroll, etc, but - ;; let M-x and C-x exit ehelp mode and retain buffer: - (suppress-keymap map) - (define-key map "\C-u" 'electric-help-undefined) - (define-key map [(control ?0)] 'electric-help-undefined) - (define-key map [(control ?1)] 'electric-help-undefined) - (define-key map [(control ?2)] 'electric-help-undefined) - (define-key map [(control ?3)] 'electric-help-undefined) - (define-key map [(control ?4)] 'electric-help-undefined) - (define-key map [(control ?5)] 'electric-help-undefined) - (define-key map [(control ?6)] 'electric-help-undefined) - (define-key map [(control ?7)] 'electric-help-undefined) - (define-key map [(control ?8)] 'electric-help-undefined) - (define-key map [(control ?9)] 'electric-help-undefined) - (define-key map (vector help-char) 'electric-help-help) - (define-key map "?" 'electric-help-help) - ;; XEmacs addition - (define-key map 'help 'electric-help-help) - (define-key map " " 'scroll-up) - (define-key map "\^?" 'scroll-down) - (define-key map "." 'beginning-of-buffer) - (define-key map "<" 'beginning-of-buffer) - (define-key map ">" 'end-of-buffer) - ;(define-key map "\C-g" 'electric-help-exit) - (define-key map "q" 'electric-help-exit) - (define-key map "Q" 'electric-help-exit) - ;;a better key than this? - (define-key map "r" 'electric-help-retain) - (define-key map "R" 'electric-help-retain) - (define-key map "\ex" 'electric-help-execute-extended) - (define-key map "\C-x" 'electric-help-ctrl-x-prefix) - - (setq electric-help-map map))) - -(defun electric-help-mode () - "`with-electric-help' temporarily places its buffer in this mode. -\(On exit from `with-electric-help', the buffer is put in `default-major-mode'.)" - (setq buffer-read-only t) - (setq mode-name "Help") - (setq major-mode 'help) - (setq modeline-buffer-identification '(" Help: %b")) - (use-local-map electric-help-map) - (add-hook 'mouse-leave-buffer-hook 'electric-help-retain) - (view-mode -1) - ;; this is done below in with-electric-help - ;(run-hooks 'electric-help-mode-hook) - ) - -;;;###autoload -(defun with-electric-help (thunk &optional buffer noerase minheight) - "Pop up an \"electric\" help buffer. -The arguments are THUNK &optional BUFFER NOERASE MINHEIGHT. -THUNK is a function of no arguments which is called to initialize the -contents of BUFFER. BUFFER defaults to `*Help*'. BUFFER will be -erased before THUNK is called unless NOERASE is non-nil. THUNK will -be called while BUFFER is current and with `standard-output' bound to -the buffer specified by BUFFER. - -If THUNK returns nil, we display BUFFER starting at the top, and -shrink the window to fit. If THUNK returns non-nil, we don't do those things. - -After THUNK has been called, this function \"electrically\" pops up a window -in which BUFFER is displayed and allows the user to scroll through that buffer -in electric-help-mode. The window's height will be at least MINHEIGHT if -this value is non-nil. - -If THUNK returns nil, we display BUFFER starting at the top, and -shrink the window to fit. If THUNK returns non-nil, we don't do those -things. - -When the user exits (with `electric-help-exit', or otherwise) the help -buffer's window disappears (i.e., we use `save-window-excursion') -BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit." - (setq buffer (get-buffer-create (or buffer "*Help*"))) - (let ((one (one-window-p t)) - (config (current-window-configuration)) - (bury nil) - (electric-help-form-to-execute nil)) - (unwind-protect - (save-excursion - (if one (goto-char (window-start (selected-window)))) - (let ((pop-up-windows t)) - (pop-to-buffer buffer)) - (save-excursion - (set-buffer buffer) - (if (and minheight (< (window-height) minheight)) - (enlarge-window (- minheight (window-height)))) - (electric-help-mode) - (setq buffer-read-only nil) - (or noerase - (erase-buffer))) - (let ((standard-output buffer)) - (if (not (funcall thunk)) - (progn - (set-buffer buffer) - (set-buffer-modified-p nil) - (goto-char (point-min)) - (if one (shrink-window-if-larger-than-buffer (selected-window)))))) - (set-buffer buffer) - (run-hooks 'electric-help-mode-hook) - (setq buffer-read-only t) - (if (eq (car-safe - ;; XEmacs: Don't be screwed by minor-modes (view-minor-mode) - (let ((overriding-local-map electric-help-map)) - (electric-help-command-loop))) - 'retain) - (setq config (current-window-configuration)) - (setq bury t))) - (message "") - (set-buffer buffer) - (setq buffer-read-only nil) - (condition-case () - (funcall (or default-major-mode 'fundamental-mode)) - (error nil)) - (set-window-configuration config) - (if bury - (progn - ;;>> Perhaps this shouldn't be done. - ;; so that when we say "Press space to bury" we mean it - (replace-buffer-in-windows buffer) - ;; must do this outside of save-window-excursion - (bury-buffer buffer))) - (eval electric-help-form-to-execute)))) - -(defun electric-help-command-loop () - (catch 'exit - (if (pos-visible-in-window-p (point-max)) - (progn (message "%s" (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>")) - ;; XEmacs change - (if (equal (setq unread-command-events - (list (next-command-event))) - '(?\ )) - (progn (setq unread-command-events nil) - (throw 'exit t))))) - (let (up down both neither - (standard (and (eq (key-binding " ") - 'scroll-up) - (eq (key-binding "\^?") - 'scroll-down) - (eq (key-binding "q") - 'electric-help-exit) - (eq (key-binding "r") - 'electric-help-retain)))) - (Electric-command-loop - 'exit - (function (lambda () - (sit-for 0) ;necessary if last command was end-of-buffer or - ;beginning-of-buffer - otherwise pos-visible-in-window-p - ;will yield a wrong result. - (let ((min (pos-visible-in-window-p (point-min))) - (max (pos-visible-in-window-p (point-max)))) - (cond (isearch-mode 'noprompt) - ((and min max) - (cond (standard "Press q to exit, r to retain ") - (neither) - (t (setq neither (substitute-command-keys "Press \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) - (min - (cond (standard "Press SPC to scroll, q to exit, r to retain ") - (up) - (t (setq up (substitute-command-keys "Press \\[scroll-up] to scroll, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) - (max - (cond (standard "Press DEL to scroll back, q to exit, r to retain ") - (down) - (t (setq down (substitute-command-keys "Press \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) - (t - (cond (standard "Press SPC to scroll, DEL to scroll back, q to exit, r to retain ") - (both) - (t (setq both (substitute-command-keys "Press \\[scroll-up] to scroll, \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))))))) - t)))) - - - -;(defun electric-help-scroll-up (arg) -; ">>>Doc" -; (interactive "P") -; (if (and (null arg) (pos-visible-in-window-p (point-max))) -; (electric-help-exit) -; (scroll-up arg))) - -(defun electric-help-exit () - ">>>Doc" - (interactive) - (throw 'exit t)) - -(defun electric-help-retain () - "Exit `electric-help', retaining the current window/buffer configuration. -\(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET -will select it.)" - (interactive) - ;; Make sure that we don't throw twice, even if two events cause - ;; calling this function: - (if (memq 'electric-help-retain mouse-leave-buffer-hook) - (progn - (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain) - (throw 'exit '(retain))))) - - -(defun electric-help-undefined () - (interactive) - (error "%s is undefined -- Press %s to exit" - (mapconcat 'single-key-description (this-command-keys) " ") - (if (eq (key-binding "q") 'electric-help-exit) - "q" - (substitute-command-keys "\\[electric-help-exit]")))) - - -;>>> this needs to be hairified (recursive help, anybody?) -(defun electric-help-help () - (interactive) - (if (and (eq (key-binding "q") 'electric-help-exit) - (eq (key-binding " ") 'scroll-up) - (eq (key-binding "\^?") 'scroll-down) - (eq (key-binding "r") 'electric-help-retain)) - (message "SPC scrolls up, DEL scrolls down, q exits burying help buffer, r exits") - (message "%s" (substitute-command-keys "\\[scroll-up] scrolls up, \\[scroll-down] scrolls down, \\[electric-help-exit] exits burying help buffer, \\[electric-help-retain] exits"))) - (sit-for 2)) - - -;;;###autoload -(defun electric-helpify (fun &optional name) - (let ((name (or name "*Help*"))) - (if (save-window-excursion - ;; kludge-o-rama - (let* ((p (symbol-function 'print-help-return-message)) - (b (get-buffer name)) - (m (buffer-modified-p b))) - (and b (not (get-buffer-window b)) - (setq b nil)) - (unwind-protect - (progn - (message "%s..." (capitalize (symbol-name fun))) - ;; with-output-to-temp-buffer marks the buffer as unmodified. - ;; kludging excessively and relying on that as some sort - ;; of indication leads to the following abomination... - ;;>> This would be doable without such icky kludges if either - ;;>> (a) there were a function to read the interactive - ;;>> args for a command and return a list of those args. - ;;>> (To which one would then just apply the command) - ;;>> (The only problem with this is that interactive-p - ;;>> would break, but that is such a misfeature in - ;;>> any case that I don't care) - ;;>> It is easy to do this for emacs-lisp functions; - ;;>> the only problem is getting the interactive spec - ;;>> for subrs - ;;>> (b) there were a function which returned a - ;;>> modification-tick for a buffer. One could tell - ;;>> whether a buffer had changed by whether the - ;;>> modification-tick were different. - ;;>> (Presumably there would have to be a way to either - ;;>> restore the tick to some previous value, or to - ;;>> suspend updating of the tick in order to allow - ;;>> things like momentary-string-display) - (and b - (save-excursion - (set-buffer b) - (set-buffer-modified-p t))) - (fset 'print-help-return-message 'ignore) - (call-interactively fun) - (and (get-buffer name) - (get-buffer-window (get-buffer name)) - (or (not b) - (not (eq b (get-buffer name))) - (not (buffer-modified-p b))))) - (fset 'print-help-return-message p) - (and b (buffer-name b) - (save-excursion - (set-buffer b) - (set-buffer-modified-p m)))))) - (with-electric-help 'ignore name t)))) - - - -;; This is to be bound to M-x in ehelp mode. Retains ehelp buffer and then -;; continues with execute-extended-command. -(defun electric-help-execute-extended (prefixarg) - (interactive "p") - (setq electric-help-form-to-execute '(execute-extended-command nil)) - (electric-help-retain)) - -;; This is to be buond to C-x in ehelp mode. Retains ehelp buffer and then -;; continues with ctrl-x prefix. -(defun electric-help-ctrl-x-prefix (prefixarg) - (interactive "p") - (setq electric-help-form-to-execute '(progn (message nil) (setq unread-command-char ?\C-x))) - (electric-help-retain)) - - -(defun electric-describe-key () - (interactive) - (electric-helpify 'describe-key)) - -(defun electric-describe-mode () - (interactive) - (electric-helpify 'describe-mode)) - -(defun electric-view-lossage () - (interactive) - (electric-helpify 'view-lossage)) - -;(defun electric-help-for-help () -; "See help-for-help" -; (interactive) -; ) - -(defun electric-describe-function () - (interactive) - (electric-helpify 'describe-function)) - -(defun electric-describe-variable () - (interactive) - (electric-helpify 'describe-variable)) - -(defun electric-describe-bindings () - (interactive) - (electric-helpify 'describe-bindings)) - -(defun electric-describe-syntax () - (interactive) - (electric-helpify 'describe-syntax)) - -(defun electric-command-apropos () - (interactive) - (electric-helpify 'command-apropos "*Apropos*")) - -;(define-key help-map "a" 'electric-command-apropos) - -(defun electric-apropos () - (interactive) - (electric-helpify 'apropos)) - - -;;;; ehelp-map - -(defvar ehelp-map ()) -(if ehelp-map - nil - ;; #### WTF? Why don't we just use substitute-key-definition - ;; like FSF does? - (let ((shadow '((apropos . electric-apropos) - (command-apropos . electric-command-apropos) - (describe-key . electric-describe-key) - (describe-mode . electric-describe-mode) - (view-lossage . electric-view-lossage) - (describe-function . electric-describe-function) - (describe-variable . electric-describe-variable) - (describe-bindings . electric-describe-bindings) - (describe-syntax . electric-describe-syntax))) - (map (make-sparse-keymap))) - (set-keymap-name map 'ehelp-map) - (set-keymap-parents map (list help-map)) - ;; Shadow bindings which would be inherited from help-map - ;;#### This doesn't descend into sub-keymaps - (map-keymap (function (lambda (key binding) - (let ((tem (assq binding shadow))) - (if tem - (define-key map key (cdr tem)))))) - help-map) - (setq ehelp-map map) - (fset 'ehelp-command map))) - -;; Do (define-key global-map "\C-h" 'ehelp-command) if you want to win - -(provide 'ehelp) - -;;; ehelp.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/electric/electric.el --- a/lisp/electric/electric.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,210 +0,0 @@ -;;; electric.el --- window maker and Command loop for `electric' modes. - -;; Copyright (C) 1985, 1986, 1995 Free Software Foundation, Inc. - -;; Author: K. Shane Hartman -;; Maintainer: FSF -;; Keywords: extensions - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Commentary: - -; zaaaaaaap - -;;; Code: - -;; This loop is the guts for non-standard modes which retain control -;; until some event occurs. It is a `do-forever', the only way out is -;; to throw. It assumes that you have set up the keymap, window, and -;; everything else: all it does is read commands and execute them - -;; providing error messages should one occur (if there is no loop -;; function - which see). The required argument is a tag which should -;; expect a value of nil if the user decides to punt. The second -;; argument is the prompt to be used: if nil, use "->", if 'noprompt, -;; don't use a prompt, if a string, use that string as prompt, and if -;; a function of no variable, it will be evaluated in every iteration -;; of the loop and its return value, which can be nil, 'noprompt or a -;; string, will be used as prompt. Given third argument non-nil, it -;; INHIBITS quitting unless the user types C-g at toplevel. This is -;; so user can do things like C-u C-g and not get thrown out. Fourth -;; argument, if non-nil, should be a function of two arguments which -;; is called after every command is executed. The fifth argument, if -;; provided, is the state variable for the function. If the -;; loop-function gets an error, the loop will abort WITHOUT throwing -;; (moral: use unwind-protect around call to this function for any -;; critical stuff). The second argument for the loop function is the -;; conditions for any error that occurred or nil if none. - -(defun Electric-command-loop (return-tag - &optional prompt inhibit-quit - loop-function loop-state) - - (let (cmd - (err nil) - (electrified-buffer (current-buffer)) ; XEmacs - - (prompt-string prompt)) - (while t - (if (not (or (stringp prompt) (eq prompt nil) (eq prompt 'noprompt))) - (setq prompt-string (funcall prompt))) - (if (not (stringp prompt-string)) - (if (eq prompt-string 'noprompt) - (setq prompt-string nil) - (setq prompt-string "->"))) - (setq cmd (read-key-sequence prompt-string)) - ;; XEmacs - (or prefix-arg (setq last-command this-command)) - (setq last-command-event (aref cmd (1- (length cmd))) - current-mouse-event - (and (or (button-press-event-p last-command-event) - (button-release-event-p last-command-event) - (misc-user-event-p last-command-event)) - last-command-event) - this-command (if (misc-user-event-p last-command-event) - last-command-event - (key-binding cmd t)) - cmd this-command) - ;; This makes universal-argument-other-key work. - (setq universal-argument-num-events 0) - (if (or (prog1 quit-flag (setq quit-flag nil)) - ;; XEmacs - (eq (event-to-character last-input-event) (quit-char))) - (progn (setq unread-command-events nil - prefix-arg nil) - ;; If it wasn't cancelling a prefix character, then quit. - (if (or (= (length (this-command-keys)) 1) - (not inhibit-quit)) ; safety - (progn (ding nil 'quit) ; XEmacs - - (message "Quit") - (throw return-tag nil)) - (setq cmd nil)))) - (setq current-prefix-arg prefix-arg) - (if cmd - (condition-case conditions - ;; XEmacs - (progn (if (eventp cmd) - (progn - (let ((b (current-buffer))) - (dispatch-event cmd) - (if (not (eq b (current-buffer))) - (throw return-tag (current-buffer))))) - (command-execute cmd)) - (setq last-command this-command) - (if (or (prog1 quit-flag (setq quit-flag nil)) - ;; XEmacs - (eq (event-to-character last-input-event) - (quit-char))) - (progn (setq unread-command-events nil) - (if (not inhibit-quit) - ;; XEmacs - (progn (ding nil 'quit) - (message "Quit") - (throw return-tag nil)) - (message "Quit inhibited") - (ding))))) - (buffer-read-only (if loop-function - (setq err conditions) - (ding) - (message "Buffer is read-only") - (sit-for 2))) - (beginning-of-buffer (if loop-function - (setq err conditions) - (ding) - (message "Beginning of Buffer") - (sit-for 2))) - (end-of-buffer (if loop-function - (setq err conditions) - (ding) - (message "End of Buffer") - (sit-for 2))) - (error (if loop-function - (setq err conditions) - (ding) - (message "Error: %s" - (if (eq (car conditions) 'error) - (car (cdr conditions)) - (prin1-to-string conditions))) - (sit-for 2)))) - (ding)) - (and (not (eq (current-buffer) electrified-buffer)) ; XEmacs - - (not (eq (selected-window) (minibuffer-window))) - (progn (ding nil 'quit) - (message "Leaving electric command loop %s." - "because buffer has changed") - (sit-for 2) - (throw return-tag nil))) - (if loop-function (funcall loop-function loop-state err)))) - ;; XEmacs - huh? It should be impossible to ever get here... - (ding nil 'alarm) - (throw return-tag nil)) - -;; This function is like pop-to-buffer, sort of. -;; The algorithm is -;; If there is a window displaying buffer -;; Select it -;; Else if there is only one window -;; Split it, selecting the window on the bottom with height being -;; the lesser of max-height (if non-nil) and the number of lines in -;; the buffer to be displayed subject to window-min-height constraint. -;; Else -;; Switch to buffer in the current window. -;; -;; Then if max-height is nil, and not all of the lines in the buffer -;; are displayed, grab the whole frame. -;; -;; Returns selected window on buffer positioned at point-min. - -(defun Electric-pop-up-window (buffer &optional max-height) - (let* ((win (or (get-buffer-window buffer) (selected-window))) - (buf (get-buffer buffer)) - (one-window (one-window-p t)) - (pop-up-windows t) - (target-height) - (lines)) - (if (not buf) - (error "Buffer %s does not exist" buffer) - (save-excursion - (set-buffer buf) - (setq lines (count-lines (point-min) (point-max))) - (setq target-height - (min (max (if max-height (min max-height (1+ lines)) (1+ lines)) - window-min-height) - (save-window-excursion - (delete-other-windows) - (1- (window-height (selected-window))))))) - (cond ((and (eq (window-buffer win) buf)) - (select-window win)) - (one-window - (goto-char (window-start win)) - (pop-to-buffer buffer) - (setq win (selected-window)) - (enlarge-window (- target-height (window-height win)))) - (t - (switch-to-buffer buf))) - (if (and (not max-height) - (> target-height (window-height (selected-window)))) - (progn (goto-char (window-start win)) - (enlarge-window (- target-height (window-height win))))) - (goto-char (point-min)) - win))) - -(provide 'electric) - -;;; electric.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/electric/helper.el --- a/lisp/electric/helper.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -;;; helper.el --- utility help package supporting help in electric modes - -;; Copyright (C) 1985 Free Software Foundation, Inc. - -;; Author: K. Shane Hartman -;; Maintainer: FSF -;; Keywords: help - -;; This file is part of XEmacs. - -;; XEmacs is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free -;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -;; 02111-1307, USA. - -;;; Synched up with: FSF 19.34. - -;;; Code: - -;; hey, here's a helping hand. - -;; Bind this to a string for in "... Other keys ". -;; Helper-help uses this to construct help string when scrolling. -;; Defaults to "return" -(defvar Helper-return-blurb nil) - -;; Keymap implementation doesn't work too well for non-standard loops. -;; But define it anyway for those who can use it. Non-standard loops -;; will probably have to use Helper-help. You can't autoload the -;; keymap either. - - -(defvar Helper-help-map nil) -(if Helper-help-map - nil - (setq Helper-help-map (make-keymap)) - ;(fillarray Helper-help-map 'undefined) - (define-key Helper-help-map "m" 'Helper-describe-mode) - (define-key Helper-help-map "b" 'Helper-describe-bindings) - (define-key Helper-help-map "c" 'Helper-describe-key-briefly) - (define-key Helper-help-map "k" 'Helper-describe-key) - ;(define-key Helper-help-map "f" 'Helper-describe-function) - ;(define-key Helper-help-map "v" 'Helper-describe-variable) - (define-key Helper-help-map "?" 'Helper-help-options) - (define-key Helper-help-map (vector help-char) 'Helper-help-options) - (fset 'Helper-help-map Helper-help-map)) - -(defun Helper-help-scroller () - (let ((blurb (or (and (boundp 'Helper-return-blurb) - Helper-return-blurb) - "return"))) - (save-window-excursion - (goto-char (window-start (selected-window))) - (if (get-buffer-window "*Help*") - (pop-to-buffer "*Help*") - (switch-to-buffer "*Help*")) - (goto-char (point-min)) - (let ((continue t) state) - (while continue - (setq state (+ (* 2 (if (pos-visible-in-window-p (point-max)) 1 0)) - (if (pos-visible-in-window-p (point-min)) 1 0))) - (message - (nth state - '("Space forward, Delete back. Other keys %s" - "Space scrolls forward. Other keys %s" - "Delete scrolls back. Other keys %s" - "Type anything to %s")) - blurb) - (setq continue (read-char)) - (cond ((and (memq continue '(?\ ?\C-v)) (< state 2)) - (scroll-up)) - ((= continue ?\C-l) - (recenter)) - ((and (= continue ?\177) (zerop (% state 2))) - (scroll-down)) - (t (setq continue nil)))))))) - -(defun Helper-help-options () - "Describe help options." - (interactive) - (message "c (key briefly), m (mode), k (key), b (bindings)") - ;(message "c (key briefly), m (mode), k (key), v (variable), f (function)") - (sit-for 4)) - -(defun Helper-describe-key-briefly (key) - "Briefly describe binding of KEY." - (interactive "kDescribe key briefly: ") - (describe-key-briefly key) - (sit-for 4)) - -(defun Helper-describe-key (key) - "Describe binding of KEY." - (interactive "kDescribe key: ") - (save-window-excursion (describe-key key)) - (Helper-help-scroller)) - -(defun Helper-describe-function () - "Describe a function. Name read interactively." - (interactive) - (save-window-excursion (call-interactively 'describe-function)) - (Helper-help-scroller)) - -(defun Helper-describe-variable () - "Describe a variable. Name read interactively." - (interactive) - (save-window-excursion (call-interactively 'describe-variable)) - (Helper-help-scroller)) - -(defun Helper-describe-mode () - "Describe the current mode." - (interactive) - (let ((name mode-name) - (documentation (documentation major-mode))) - (save-excursion - (set-buffer (get-buffer-create "*Help*")) - (erase-buffer) - (insert name " Mode\n" documentation) - (help-mode))) - (Helper-help-scroller)) - -;;;###autoload -(defun Helper-describe-bindings () - "Describe local key bindings of current mode." - (interactive) - (message "Making binding list...") - (save-window-excursion (describe-bindings)) - (Helper-help-scroller)) - -;;;###autoload -(defun Helper-help () - "Provide help for current mode." - (interactive) - (let ((continue t) c) - (while continue - (message "Help (Type ? for further options)") - (setq c (read-key-sequence nil)) - (setq c (lookup-key Helper-help-map c)) - (cond ((eq c 'Helper-help-options) - (Helper-help-options)) - ((commandp c) - (call-interactively c) - (setq continue nil)) - (t - (ding) - (setq continue nil)))))) - -(provide 'helper) - -;;; helper.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/eos/sun-eos-toolbar.el --- a/lisp/eos/sun-eos-toolbar.el Mon Aug 13 10:03:54 2007 +0200 +++ b/lisp/eos/sun-eos-toolbar.el Mon Aug 13 10:04:58 2007 +0200 @@ -14,7 +14,7 @@ ;;; Code: (defvar eos::toolbar-icon-directory - (file-name-as-directory (expand-file-name "eos" data-directory))) + (file-name-as-directory (locate-data-directory "eos"))) (defvar eos::toolbar-run-icon (if (featurep 'xpm) diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/ChangeLog --- a/lisp/eterm/ChangeLog Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,149 +0,0 @@ -1997-09-30 SL Baur - - * term.el (term-mode): Use window-displayed-height instead of - window-height. - (term-check-size): Ditto. - From Glynn Clements - -1997-06-04 Steven L Baur - - * term.el (make-term): Fix docstring. - -Sun Dec 22 00:38:46 1996 Sudish Joseph - - * tgud.el (tgud-gdb-complete-filter): Match carriage returns as - well as line feeds. - -Tue Jun 13 16:38:40 1995 Per Bothner - - * term.el: Various optimizations. The main one is to optimize for - simple output at the end of the buffer, with no paging, and in that - case to defer scrolling while we can. - (term-emulate-terminal): Don't call term-handle-scroll in - simple cases unless we are either paging or term-scroll-with-delete. - (term-down): Likewise. - (term-handle-scroll): Modify accordingly. - (term-emulate-terminal): Avoid deleting old text in common case. - Optimize the simple case of CRLF when we're at buffer end. - Handle deferred scroll when done processing output. - (term-handle-deferred-scroll): New function. - (term-down): Simplify - no longer take RIGHT argument. Tune. - (term-goto): Use term-move-columns to compensate for the above. - -Sat Jun 10 23:10:52 1995 Per Bothner - - * term.el (term-escape-char, term-set-escape-char): Add doc-string. - (term-mouse-paste): Add xemacs support. - - * term.el: Various speed enhencements: - (term-handle-scroll): Don't clear term-current-row; maybe adjust it. - (term-down): Don't call term-adjust-current-row-cache if we've - done term-handle-scroll. - (term-emulate-terminal): Don't call term-adjust-current-row-cache. - (term-emulate-terminal): For TAB, don't nil term-start-line-column. - (term-goto): Possible optimization. - -Wed Mar 15 17:20:26 1995 Per Bothner - - * term.el (term-mouse-paste): Make work for xemacs-19.11. - For GNU emacs, don't mouse-set-point, but do - run-hooks on mouse-leave-buffer-hook, - - * term.el (term-char-mode): Fix paren error that caused - the arrow keys to not be recognized under xemacs. - Also, simplify/fix [(button2)] to [button2] for paste under xemacs. - -Tue Mar 7 16:43:51 1995 Per Bothner - - * term.el (term-eol-on-send): New variable. - (term-send-input): Move point to eol before sending only if - term-eol-on-send is true. - - * term.el (term-send-input): Don't move process-mark until - after possible 'history processing. - -Tue Feb 7 02:59:59 1995 Richard Stallman - - * term.el (term-protocol-version): Renamed from term-version. - -Sat Feb 4 16:23:18 1995 Per Bothner - - * term.el (term-version): Increased to 0.95. - (term-pager-enabled): New macro. Use it a bunch of places. - (term-terminal-menu): Clean up initialization so we don't get - complaints when re-loading term.el. - (term-send-raw-meta): Redo to handle meta-symbols (e.g. meta-delete). - More robust checking of parameter to make-string. - (term-update-mode-line): New function. Call it whenever we change - char/line/paging mode. Now includes "page" in mode-line-process - if paging is abled. - - * term.el: Remove causes for byte-compilation to complain: - (term-terminal-pos): Declare x and y in let-binding. - (term-send-invisible): Remove bogus second "iteractive" call. - (term-*): Provide defvars for lots of buffer-local variables. - (term-mode): Make comments and initial value setting from - here to the corresponding defvar. - (term-line-start-column): Remove unused variable. - (term-erase-in-line): Fix syntax (incorrect parenthesis) error. - (term-erase-in-display): Fix typo "\?n" -> "?\n". - - * term.el: Make Unix "resize" command work: - (term-handle-ansi-escape): On "\e[row;colH", limit row - and col to size of window. (Resize sends "999;999".) - (term-handle-ansi-escape): Implement "\e[6n" "Report cursor - position". This requires that we pass proc as an extra parameter. - (term-scroll-region): An empty region means extend to window bottom. - -Fri Jan 20 14:07:31 1995 Per Bothner - - * term.el (term-version): Increased to 0.94. - (term-if-emacs19, term-if-xemacs, term-ifnot-xemacs): New macros - to conditionalize at compile-time for different emacs versions. - (various places): Use them (instead of term-is-XXXX). - (term-is-emacs19): Removed, no longer needed. - - * term.el: Change keybindings to not use C-c LETTER, for - term-char-mode, term-line-mode. Keybindings for term-pager-enable - and term-pager-disable replaced by one for term-pager-toggle. - (term-pager-toggle): New function. - - * term.el (term-fake-pager-enable, term-fake-pager-disable): - Define as aliases, so that menubar code will find proper keybindings. - (term-char-mode): Make no-op if already in char mode. - (term-line-mode): Make no-op if already in line mode. - (term-mode-map): Add keybinding for no-op term-line-mode, so - code to display menubar keybindings doesn't lose it. (Needed - as long as char-mode and line-mode share term-terminal-menu.) - (term-raw-escape-map): Likewise for term-char-mode. - (term-char-mode, term-line-mode): Better documentation strings. - - * term.el: Added menubar for pager sub-mode. - -Wed Jan 11 17:06:37 1995 Per Bothner - - * term.el (term-command-hook): Disabled the feature that allowed - inferior to send a lisp command to emacs - too big a security hole. - -Mon Nov 21 12:38:05 1994 Per Bothner - - * term.el (term-termcap-format): Add cd capability. Fix ei. - (term-exec-1): Pass $TERMINFO instead of $TERMCAP if appropriate. - (term-exec-1): Pass emacs-version and term-version in $TERM. - (term-exec-1): Re-write to set process-environment. - -Sun Jun 26 20:31:52 1994 Per Bothner (bothner@kalessin.cygnus.com) - - * term.el: Set version number to 0.92. - * term.el (term): New top-level function. - -Tue May 17 11:45:21 1994 Per Bothner (bothner@kalessin.cygnus.com) - - * term.el (term-emulate-terminal): Move most of the scrolling - and other final actions inside the body of the unwind-protect. - But make sure to select the original selected window in the - cleanup actions. Bug reported by David Hampton . - - * term.el (term-emulate-terminal): Ignore ?\016 (Shift Out) - and ?\017 (Shift In). (These are produced by the Lynx WWW-viewer.) - diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/QUESTIONS --- a/lisp/eterm/QUESTIONS Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -- What should be the default escape key for char mode? - Currently; I'm using ^C. - -- What other keybindings should we have for char mode? - -- What terminal type should we use? - The old shell.el defined TERM=emacs. - To avoid confusion, we should use something different. (E.g. if TERM - is "emacs", bash turns off editing, which is not what we want.) - I'm currently using TERM=emacs-terminal. - This is somewhat verbose. - Other ideas: TERM=eterm TERM=emacsterm TERM=emacst. - -- How should buffer-local variables be defined and documented? - -; Features in comint.el not supported: -; comint-scroll-to-bottom-on-input -; comint-process-echoes (would be always true) -; comint-password-prompt-regexp (not useful) -; comint-watch-for-password-prompt (not useful) -; comint-eol-on-send -; comint-run -; comint-preinput-scroll-to-bottom -; comint-postoutput-scroll-to-bottom (inlined into term-emulate-terminal). - -; Should set EMACS env var to emacs-version? -; Should set TERM to vt100 if using terminfo? -; Should we set COLUMNS if using terminfo? -; New C-c kodes? diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/README.term --- a/lisp/eterm/README.term Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -This new term-mode is a merge of the comint shell mode with a -ANSI-compatible terminal-emulator. - -If you're using emacs-19.23 (or newer) or xemacs-19.11 (or newer), -and only want the terminal-emulator itself, just load the file -term.el. (You probably want to byte-compile it first, especially -if you have a slow machine.) - -To start term do M-x term RETURN. - -Compared to terminal.el: -* Uses standard ANSI (vt102) escape sequences. -* High-lighting (inverse video, underline, bold) are supported. -* Fully integrated into shell mode. -* Can switch back and forth between character mode (acts like xterm) - and line mode (acts like old shell mode). -* Tab and line breaks are stored in buffer (so cut and paste will get - the correct tabs and line breaks), but terminal motion uses the - "visible" layout of the screen (and display programs can assume - tab, cr and lf work as on plain terminal). - -In character ("raw") sub-mode: -Each character type is sent to the inferior process, except for C-c. -C-c C-c Send a C-c to the inferior. -C-c C-j Enter line sub-mode -C-c OTHER Same as cooked C-x map -Can use bash line editing, filename completion, and history. -Can run emacs in an emacs window! (bash users first do: export -n DISPLAY) - -In line ("cooked") mode: -Like traditional shell mode -C-c C-k Enter character sub-mode - -Either character or line sub-mode: -C-c C-q Toggle pager sub-mode (enable or disable) -The "pager" provides functionality similar to the "more" program: -Whenever a screenful has been received, emacs stops reading from -the process until you type the appropriate key. (The key 'h' provides help.) -The pager is smart enough that you can leave it on, even while -running full-screen interactive programs inside a shell window. -(The pager does not work under xemacs 19.11.) - -The file tshell.el is a preliminary replacement for shell mode. -After loading it, you invoke it with M-x tshell RET. -This needs a little work, and is not recommended. It differs from -term-mode in that it starts in line mode, and it performs directory -tracking. Such directory tracking cannot be made reliable. -It you're running bash, it is better to just use term-mode and have -bash tell term the current directory. You can do that by adding -the following to your ~/.bashrc: - - if [ "$TERM" = "eterm" ]; then - PROMPT_COMMAND='echo "/${PWD}"' - fi - -The file tgud.el is a preliminary replacement for gud.el, including -gdb-mode. After loading it, invoke "tgdb-mode" with M-x tgdb RET. - -An alternative is to run gdb from term (or tshell) mode. -Just start gdb with the --fullname flag. This will cause gdb to -ask emacs to display proper source frame on break-points - -even over a telnet/rlogin link! You would not be able to use the -gud-specific commands, but you can use gdb/readline line editing. - -If you're using terminfo, copy the e directory (itself, not just -the files in it) into the emacs 'etc' directory (as given by -ESC ESC data-directory RET), so you have ..../etc/e/eterm. -(Your system uses terminfo if ESC ESC (boundp 'system-uses-terminfo) RET -return t.) If you can't do that, replace the word "data-directory" -in term.el by a string naming this directory. - -The file TODO.term notes ideas for improvements. - -The file term.texi contain some notes that one day may become part -of a manual. - -Term.el will be in the next emacs release from the FSF. -It will also probably be in the next xemacs release. -The comint-based shell.el and gud.el will be replaced later. -Telnet.el can then be junked. -Long-term, term.el will replace comint.el, but can co-exist with it. - -Comments and bug fixes should be sent to Per Bothner (bothner@cygnus.com). -Note that I'm new to emacs hacking, so improvements are very welcome. diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/TODO.term --- a/lisp/eterm/TODO.term Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -* Define a sentinel function, so that the display doesn't get -screwed up the default sentinel when the process finishes. - -* Performance improvements? (It is zippy enough on reasonably -fast machines, though.) - -* Should more terminal escape sequences be supported? -Yes: At least the ANSI color escapes (as in colour_xterm). - -* The caching variables (e.g. term-current-row) assume that there -is be no random editing of the buffer that we don't know about. In that -respect, they are somewhat fragile. - -* Document the internals better, and make it easier to write -emulators for other kinds of terminals. - -* The scrolling behavior is still not quite right. - -* Stallman has expressed dislike for the xterm style of switching to the -alternate buffer on the "ti" capability. An alternative would be to -defer this until the screen is cleared. That assumes there are programs -that emit ti without following that by a command to erase the window. -I'm not sure there are any such programs (that we care about) ... - -*** CHANGES THAT REQUIRE NEW EMACS PRIMITIVES *** - -* If ioctl is made accessible to elisp, it may be possible -to support some kind of automatic switching between char mode -and line mode. It also becomes possible to privide term -primitives to turn off echoing in the inferior. - -*** CHANGES TO DO IN OTHER PROGRAMS *** - -* In gdb-mode, a keysequence like \C-c\C-s works by sending the command -"step" in gdb-mode. Emacs goes to a fair bit of trouble to delete the -prompt preceding the command, as well as the echo from the inferior. -In addition to being hairy, it is somewhat fragile (because of possible -type-ahead, and because the inferior might be mixing other output with -the echo). -More robust would be for emacs to send the command "noecho step" (or -"step #noecho") where the "noecho" is an instruction to gdb (readline) -to erase the prompt for this command, and suppress its echo. - -* Bash (and perhaps other shells) should be modified so that before -the prompt (and PROMPT_COMMAND) are printed, they emit: - printf("\032/%s\n", PWD); -This will tell the shell window which directory it should assume, -and obviates the need for all that hairy directory tracking. diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/auto-autoloads.el --- a/lisp/eterm/auto-autoloads.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -;;; DO NOT MODIFY THIS FILE -(if (featurep 'eterm-autoloads) (error "Already loaded")) - -;;;### (autoloads (term make-term) "term" "eterm/term.el") - -(autoload 'make-term "term" "\ -Make a term process NAME in a buffer, running PROGRAM. -The name of the buffer is made by surrounding NAME with `*'s. -If there is already a running process in that buffer, it is not restarted. -Optional third arg STARTFILE is the name of a file to send the contents of to -the process. Any more args are arguments to PROGRAM." nil nil) - -(autoload 'term "term" "\ -Start a terminal-emulator in a new buffer." t nil) - -;;;*** - -;;;### (autoloads (tperldb txdb tdbx tsdb tgdb) "tgud" "eterm/tgud.el") - -(autoload 'tgdb "tgud" "\ -Run gdb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -(autoload 'tsdb "tgud" "\ -Run sdb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -(autoload 'tdbx "tgud" "\ -Run dbx on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -(autoload 'txdb "tgud" "\ -Run xdb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger. - -You can set the variable 'tgud-xdb-directories' to a list of program source -directories if your program contains sources from more than one directory." t nil) - -(autoload 'tperldb "tgud" "\ -Run perldb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." t nil) - -;;;*** - -;;;### (autoloads (tshell) "tshell" "eterm/tshell.el") - -(defvar tshell-prompt-pattern "^[^#$%>\n]*[#$%>] *" "\ -Regexp to match prompts in the inferior shell. -Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well. -This variable is used to initialise `term-prompt-regexp' in the -shell buffer. - -The pattern should probably not match more than one line. If it does, -tshell-mode may become confused trying to distinguish prompt from input -on lines which don't start with a prompt. - -This is a fine thing to set in your `.emacs' file.") - -(autoload 'tshell "tshell" "\ -Run an inferior shell, with I/O through buffer *shell*. -If buffer exists but shell process is not running, make new shell. -If buffer exists and shell process is running, just switch to buffer `*shell*'. -Program used comes from variable `explicit-shell-file-name', - or (if that is nil) from the ESHELL environment variable, - or else from SHELL if there is no ESHELL. -If a file `~/.emacs_SHELLNAME' exists, it is given as initial input - (Note that this may lose due to a timing error if the shell - discards input when it starts up.) -The buffer is put in Tshell mode, giving commands for sending input -and controlling the subjobs of the shell. See `tshell-mode'. -See also the variable `tshell-prompt-pattern'. - -The shell file name (sans directories) is used to make a symbol name -such as `explicit-csh-args'. If that symbol is a variable, -its value is used as a list of arguments when invoking the shell. -Otherwise, one argument `-i' is passed to the shell. - -\(Type \\[describe-mode] in the shell buffer for a list of commands.)" t nil) - -;;;*** - -(provide 'eterm-autoloads) diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/custom-load.el --- a/lisp/eterm/custom-load.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -;;; custom-load.el --- automatically extracted custom dependencies - - -;;; Code: - -(custom-add-loads 'shell '("term")) -(custom-add-loads 'term '("term")) -(custom-add-loads 'processes '("term")) -(custom-add-loads 'unix '("term")) - -;;; custom-load.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/term.el --- a/lisp/eterm/term.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3334 +0,0 @@ -;;; term.el --- general command interpreter in a window stuff - -;; Copyright (C) 1988-1995, 1997 Free Software Foundation, Inc. - -;; Author: Per Bothner -;; Based on comint mode written by: Olin Shivers -;; Keyword: processes - -;; 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 2, 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; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: - -;; The changelog is at the end of this file. - -;; Please send me bug reports, bug fixes, and extensions, so that I can -;; merge them into the master source. -;; - Per Bothner (bothner@cygnus.com) - -;; This file defines a general command-interpreter-in-a-buffer package -;; (term mode). The idea is that you can build specific process-in-a-buffer -;; modes on top of term mode -- e.g., lisp, shell, scheme, T, soar, .... -;; This way, all these specific packages share a common base functionality, -;; and a common set of bindings, which makes them easier to use (and -;; saves code, implementation time, etc., etc.). - -;; For hints on converting existing process modes (e.g., tex-mode, -;; background, dbx, gdb, kermit, prolog, telnet) to use term-mode -;; instead of shell-mode, see the notes at the end of this file. - - -;; Brief Command Documentation: -;;============================================================================ -;; Term Mode Commands: (common to all derived modes, like cmushell & cmulisp -;; mode) -;; -;; m-p term-previous-input Cycle backwards in input history -;; m-n term-next-input Cycle forwards -;; m-r term-previous-matching-input Previous input matching a regexp -;; m-s comint-next-matching-input Next input that matches -;; return term-send-input -;; c-c c-a term-bol Beginning of line; skip prompt. -;; c-d term-delchar-or-maybe-eof Delete char unless at end of buff. -;; c-c c-u term-kill-input ^u -;; c-c c-w backward-kill-word ^w -;; c-c c-c term-interrupt-subjob ^c -;; c-c c-z term-stop-subjob ^z -;; c-c c-\ term-quit-subjob ^\ -;; c-c c-o term-kill-output Delete last batch of process output -;; c-c c-r term-show-output Show last batch of process output -;; c-c c-h term-dynamic-list-input-ring List input history -;; -;; Not bound by default in term-mode -;; term-send-invisible Read a line w/o echo, and send to proc -;; (These are bound in shell-mode) -;; term-dynamic-complete Complete filename at point. -;; term-dynamic-list-completions List completions in help buffer. -;; term-replace-by-expanded-filename Expand and complete filename at point; -;; replace with expanded/completed name. -;; term-kill-subjob No mercy. -;; term-show-maximum-output Show as much output as possible. -;; term-continue-subjob Send CONT signal to buffer's process -;; group. Useful if you accidentally -;; suspend your process (with C-c C-z). - -;; term-mode-hook is the term mode hook. Basically for your keybindings. -;; term-load-hook is run after loading in this package. - -;; Code: - -;; This is passed to the inferior in the EMACS environment variable, -;; so it is important to increase it if there are protocol-relevant changes. -(defconst term-protocol-version "0.95") - -(require 'ring) -(require 'ehelp) - -(if (fboundp 'defgroup) nil - (defmacro defgroup (&rest forms) nil) - (defmacro defcustom (name init doc &rest forms) - (list 'defvar name init doc))) - -(defgroup term nil - "General command interpreter in a window" - :group 'processes - :group 'unix) - - -;;; Buffer Local Variables: -;;;============================================================================ -;;; Term mode buffer local variables: -;;; term-prompt-regexp - string term-bol uses to match prompt. -;;; term-delimiter-argument-list - list For delimiters and arguments -;;; term-last-input-start - marker Handy if inferior always echoes -;;; term-last-input-end - marker For term-kill-output command -;; For the input history mechanism: -(defvar term-input-ring-size 32 "Size of input history ring.") -;;; term-input-ring-size - integer -;;; term-input-ring - ring -;;; term-input-ring-index - number ... -;;; term-input-autoexpand - symbol ... -;;; term-input-ignoredups - boolean ... -;;; term-last-input-match - string ... -;;; term-dynamic-complete-functions - hook For the completion mechanism -;;; term-completion-fignore - list ... -;;; term-get-old-input - function Hooks for specific -;;; term-input-filter-functions - hook process-in-a-buffer -;;; term-input-filter - function modes. -;;; term-input-send - function -;;; term-scroll-to-bottom-on-output - symbol ... -;;; term-scroll-show-maximum-output - boolean... -(defvar term-height) ;; Number of lines in window. -(defvar term-width) ;; Number of columns in window. -(defvar term-home-marker) ;; Marks the "home" position for cursor addressing. -(defvar term-saved-home-marker nil) ;; When using alternate sub-buffer, -;; contains saved term-home-marker from original sub-buffer . -(defvar term-start-line-column 0) ;; (current-column) at start of screen line, -;; or nil if unknown. -(defvar term-current-column 0) ;; If non-nil, is cache for (current-column). -(defvar term-current-row 0) ;; Current vertical row (relative to home-marker) -;; or nil if unknown. -(defvar term-insert-mode nil) -(defvar term-vertical-motion) -(defvar term-terminal-state 0) ;; State of the terminal emulator: -;; state 0: Normal state -;; state 1: Last character was a graphic in the last column. -;; If next char is graphic, first move one column right -;; (and line warp) before displaying it. -;; This emulates (more or less) the behavior of xterm. -;; state 2: seen ESC -;; state 3: seen ESC [ (or ESC [ ?) -;; state 4: term-terminal-parameter contains pending output. -(defvar term-kill-echo-list nil) ;; A queue of strings whose echo -;; we want suppressed. -(defvar term-terminal-parameter) -(defvar term-terminal-previous-parameter) -(defvar term-current-face 'default) -(defvar term-scroll-start 0) ;; Top-most line (inclusive) of scrolling region. -(defvar term-scroll-end) ;; Number of line (zero-based) after scrolling region. -(defvar term-pager-count nil) ;; If nil, paging is disabled. -;; Otherwise, number of lines before we need to page. -(defvar term-saved-cursor nil) -(defvar term-command-hook) -(defvar term-log-buffer nil) -(defvar term-scroll-with-delete nil) ;; term-scroll-with-delete is t if -;; forward scrolling should be implemented by delete to -;; top-most line(s); and nil if scrolling should be implemented -;; by moving term-home-marker. It is set to t iff there is a -;; (non-default) scroll-region OR the alternate buffer is used. -(defvar term-pending-delete-marker) ;; New user input in line mode needs to -;; be deleted, because it gets echoed by the inferior. -;; To reduce flicker, we defer the delete until the next output. -(defvar term-old-mode-map nil) ;; Saves the old keymap when in char mode. -(defvar term-old-mode-line-format) ;; Saves old mode-line-format while paging. -(defvar term-pager-old-local-map nil) ;; Saves old keymap while paging. -(defvar term-pager-old-filter) ;; Saved process-filter while paging. - -(defcustom explicit-shell-file-name nil - "*If non-nil, is file name to use for explicitly requested inferior shell." - :type '(choice (const nil) file) - :group 'term) - -(defvar term-prompt-regexp "^" - "Regexp to recognise prompts in the inferior process. -Defaults to \"^\", the null string at BOL. - -Good choices: - Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp) - Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\" - franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\" - kcl: \"^>+ *\" - shell: \"^[^#$%>\\n]*[#$%>] *\" - T: \"^>+ *\" - -This is a good thing to set in mode hooks.") - -(defvar term-delimiter-argument-list () - "List of characters to recognise as separate arguments in input. -Strings comprising a character in this list will separate the arguments -surrounding them, and also be regarded as arguments in their own right (unlike -whitespace). See `term-arguments'. -Defaults to the empty list. - -For shells, a good value is (?\\| ?& ?< ?> ?\\( ?\\) ?;). - -This is a good thing to set in mode hooks.") - -(defcustom term-input-autoexpand nil - "*If non-nil, expand input command history references on completion. -This mirrors the optional behavior of tcsh (its autoexpand and histlit). - -If the value is `input', then the expansion is seen on input. -If the value is `history', then the expansion is only when inserting -into the buffer's input ring. See also `term-magic-space' and -`term-dynamic-complete'. - -This variable is buffer-local." - :type '(choice (const nil) (const t) (const input) (const history)) - :group 'term) - -(defcustom term-input-ignoredups nil - "*If non-nil, don't add input matching the last on the input ring. -This mirrors the optional behavior of bash. - -This variable is buffer-local." - :type 'boolean - :group 'term) - -(defcustom term-input-ring-file-name nil - "*If non-nil, name of the file to read/write input history. -See also `term-read-input-ring' and `term-write-input-ring'. - -This variable is buffer-local, and is a good thing to set in mode hooks." - :type 'boolean - :group 'term) - -(defcustom term-scroll-to-bottom-on-output nil - "*Controls whether interpreter output causes window to scroll. -If nil, then do not scroll. If t or `all', scroll all windows showing buffer. -If `this', scroll only the selected window. -If `others', scroll only those that are not the selected window. - -The default is nil. - -See variable `term-scroll-show-maximum-output'. This variable is buffer-local." - :type '(choice (const :tag "off" nil) - (const t) - (const all) - (const this) - (const others)) - :group 'term) - -(defcustom term-scroll-show-maximum-output nil - "*Controls how interpreter output causes window to scroll. -If non-nil, then show the maximum output when the window is scrolled. - -See variable `term-scroll-to-bottom-on-output'. -This variable is buffer-local." - :type 'boolean - :group 'term) - -;; Where gud-display-frame should put the debugging arrow. This is -;; set by the marker-filter, which scans the debugger's output for -;; indications of the current pc. -(defvar term-pending-frame nil) - -;;; Here are the per-interpreter hooks. -(defvar term-get-old-input (function term-get-old-input-default) - "Function that submits old text in term mode. -This function is called when return is typed while the point is in old text. -It returns the text to be submitted as process input. The default is -term-get-old-input-default, which grabs the current line, and strips off -leading text matching term-prompt-regexp") - -(defvar term-dynamic-complete-functions - '(term-replace-by-expanded-history term-dynamic-complete-filename) - "List of functions called to perform completion. -Functions should return non-nil if completion was performed. -See also `term-dynamic-complete'. - -This is a good thing to set in mode hooks.") - -(defvar term-input-filter - (function (lambda (str) (not (string-match "\\`\\s *\\'" str)))) - "Predicate for filtering additions to input history. -Only inputs answering true to this function are saved on the input -history list. Default is to save anything that isn't all whitespace") - -(defvar term-input-filter-functions '() - "Functions to call before input is sent to the process. -These functions get one argument, a string containing the text to send. - -This variable is buffer-local.") - -(defvar term-input-sender (function term-simple-send) - "Function to actually send to PROCESS the STRING submitted by user. -Usually this is just 'term-simple-send, but if your mode needs to -massage the input string, this is your hook. This is called from -the user command term-send-input. term-simple-send just sends -the string plus a newline.") - -(defcustom term-eol-on-send t - "*Non-nil means go to the end of the line before sending input. -See `term-send-input'." - :type 'boolean - :group 'term) - -(defcustom term-mode-hook '() - "Called upon entry into term-mode -This is run before the process is cranked up." - :type 'hook - :group 'term) - -(defcustom term-exec-hook '() - "Called each time a process is exec'd by term-exec. -This is called after the process is cranked up. It is useful for things that -must be done each time a process is executed in a term-mode buffer (e.g., -\(process-kill-without-query)). In contrast, the term-mode-hook is only -executed once when the buffer is created." - :type 'hook - :group 'term) - -(defvar term-mode-map nil) -(defvar term-raw-map nil - "Keyboard map for sending characters directly to the inferior process.") -(defvar term-escape-char nil - "Escape character for char-sub-mode of term mode. -Do not change it directly; use term-set-escape-char instead.") -(defvar term-raw-escape-map nil) - -(defvar term-pager-break-map nil) - -(defvar term-ptyp t - "True if communications via pty; false if by pipe. Buffer local. -This is to work around a bug in emacs process signaling.") - -(defvar term-last-input-match "" - "Last string searched for by term input history search, for defaulting. -Buffer local variable.") - -(defvar term-input-ring nil) -(defvar term-last-input-start) -(defvar term-last-input-end) -(defvar term-input-ring-index nil - "Index of last matched history element.") -(defvar term-matching-input-from-input-string "" - "Input previously used to match input history.") -; This argument to set-process-filter disables reading from the process, -; assuming this is emacs-19.20 or newer. -(defvar term-pager-filter t) - -(put 'term-replace-by-expanded-history 'menu-enable 'term-input-autoexpand) -(put 'term-input-ring 'permanent-local t) -(put 'term-input-ring-index 'permanent-local t) -(put 'term-input-autoexpand 'permanent-local t) -(put 'term-input-filter-functions 'permanent-local t) -(put 'term-scroll-to-bottom-on-output 'permanent-local t) -(put 'term-scroll-show-maximum-output 'permanent-local t) -(put 'term-ptyp 'permanent-local t) - -;; Do FORMS if running under Emacs-19. -(defmacro term-if-emacs19 (&rest forms) - (if (string-match "^19" emacs-version) (cons 'progn forms))) -;; True if running under XEmacs (previously Lucid emacs). -(defmacro term-is-xemacs () '(string-match "Lucid" emacs-version)) -;; Do FORM if running under XEmacs (previously Lucid emacs). -(defmacro term-if-xemacs (&rest forms) - (if (term-is-xemacs) (cons 'progn forms))) -;; Do FORM if NOT running under XEmacs (previously Lucid emacs). -(defmacro term-ifnot-xemacs (&rest forms) - (if (not (term-is-xemacs)) (cons 'progn forms))) - -(defmacro term-in-char-mode () '(eq (current-local-map) term-raw-map)) -(defmacro term-in-line-mode () '(not (term-in-char-mode))) -;; True if currently doing PAGER handling. -(defmacro term-pager-enabled () 'term-pager-count) -(defmacro term-handling-pager () 'term-pager-old-local-map) -(defmacro term-using-alternate-sub-buffer () 'term-saved-home-marker) - -(defvar term-signals-menu) -(defvar term-terminal-menu) - -(term-if-xemacs - (defvar term-terminal-menu - '("Terminal" - [ "Character mode" term-char-mode (term-in-line-mode)] - [ "Line mode" term-line-mode (term-in-char-mode)] - [ "Enable paging" term-pager-toggle (not term-pager-count)] - [ "Disable paging" term-pager-toggle term-pager-count]))) - -(defun term-mode () - "Major mode for interacting with an inferior interpreter. -Interpreter name is same as buffer name, sans the asterisks. -In line sub-mode, return at end of buffer sends line as input, -while return not at end copies rest of line to end and sends it. -In char sub-mode, each character (except `term-escape-char`) is -set immediately. - -This mode is typically customised to create inferior-lisp-mode, -shell-mode, etc.. This can be done by setting the hooks -term-input-filter-functions, term-input-filter, term-input-sender and -term-get-old-input to appropriate functions, and the variable -term-prompt-regexp to the appropriate regular expression. - -An input history is maintained of size `term-input-ring-size', and -can be accessed with the commands \\[term-next-input], \\[term-previous-input], and \\[term-dynamic-list-input-ring]. -Input ring history expansion can be achieved with the commands -\\[term-replace-by-expanded-history] or \\[term-magic-space]. -Input ring expansion is controlled by the variable `term-input-autoexpand', -and addition is controlled by the variable `term-input-ignoredups'. - -Input to, and output from, the subprocess can cause the window to scroll to -the end of the buffer. See variables `term-scroll-to-bottom-on-input', -and `term-scroll-to-bottom-on-output'. - -If you accidentally suspend your process, use \\[term-continue-subjob] -to continue it. - -\\{term-mode-map} - -Entry to this mode runs the hooks on term-mode-hook" - (interactive) - ;; Do not remove this. All major modes must do this. - (kill-all-local-variables) - (setq major-mode 'term-mode) - (setq mode-name "Term") - (use-local-map term-mode-map) - (make-local-variable 'term-home-marker) - (setq term-home-marker (copy-marker 0)) - (make-local-variable 'term-saved-home-marker) - (make-local-variable 'term-height) - (make-local-variable 'term-width) - (setq term-width (1- (window-width))) - (setq term-height (1- (window-displayed-height))) - (make-local-variable 'term-terminal-parameter) - (make-local-variable 'term-saved-cursor) - (make-local-variable 'term-last-input-start) - (setq term-last-input-start (make-marker)) - (make-local-variable 'term-last-input-end) - (setq term-last-input-end (make-marker)) - (make-local-variable 'term-last-input-match) - (setq term-last-input-match "") - (make-local-variable 'term-prompt-regexp) ; Don't set; default - (make-local-variable 'term-input-ring-size) ; ...to global val. - (make-local-variable 'term-input-ring) - (make-local-variable 'term-input-ring-file-name) - (or (and (boundp 'term-input-ring) term-input-ring) - (setq term-input-ring (make-ring term-input-ring-size))) - (make-local-variable 'term-input-ring-index) - (or (and (boundp 'term-input-ring-index) term-input-ring-index) - (setq term-input-ring-index nil)) - - (make-local-variable 'term-command-hook) - (setq term-command-hook (symbol-function 'term-command-hook)) - - (make-local-variable 'term-terminal-state) - (make-local-variable 'term-kill-echo-list) - (make-local-variable 'term-start-line-column) - (make-local-variable 'term-current-column) - (make-local-variable 'term-current-row) - (make-local-variable 'term-log-buffer) - (make-local-variable 'term-scroll-start) - (make-local-variable 'term-scroll-end) - (setq term-scroll-end term-height) - (make-local-variable 'term-scroll-with-delete) - (make-local-variable 'term-pager-count) - (make-local-variable 'term-pager-old-local-map) - (make-local-variable 'term-old-mode-map) - (make-local-variable 'term-insert-mode) - (make-local-variable 'term-dynamic-complete-functions) - (make-local-variable 'term-completion-fignore) - (make-local-variable 'term-get-old-input) - (make-local-variable 'term-matching-input-from-input-string) - (make-local-variable 'term-input-autoexpand) - (make-local-variable 'term-input-ignoredups) - (make-local-variable 'term-delimiter-argument-list) - (make-local-variable 'term-input-filter-functions) - (make-local-variable 'term-input-filter) - (make-local-variable 'term-input-sender) - (make-local-variable 'term-eol-on-send) - (make-local-variable 'term-scroll-to-bottom-on-output) - (make-local-variable 'term-scroll-show-maximum-output) - (make-local-variable 'term-ptyp) - (make-local-variable 'term-exec-hook) - (make-local-variable 'term-vertical-motion) - (make-local-variable 'term-pending-delete-marker) - (setq term-pending-delete-marker (make-marker)) - (make-local-variable 'term-current-face) - (make-local-variable 'term-pending-frame) - (setq term-pending-frame nil) - (run-hooks 'term-mode-hook) - (term-if-xemacs - (if (fboundp 'add-submenu) - (progn - (set (make-local-variable 'current-menubar) - (copy-sequence current-menubar)) - (add-submenu nil term-terminal-menu)))) - (or term-input-ring - (setq term-input-ring (make-ring term-input-ring-size))) - (term-update-mode-line)) - -(if term-mode-map - nil - (setq term-mode-map (make-sparse-keymap)) - (define-key term-mode-map "\ep" 'term-previous-input) - (define-key term-mode-map "\en" 'term-next-input) - (define-key term-mode-map "\er" 'term-previous-matching-input) - (define-key term-mode-map "\es" 'term-next-matching-input) - (term-ifnot-xemacs - (define-key term-mode-map [?\A-\M-r] 'term-previous-matching-input-from-input) - (define-key term-mode-map [?\A-\M-s] 'term-next-matching-input-from-input)) - (define-key term-mode-map "\e\C-l" 'term-show-output) - (define-key term-mode-map "\C-m" 'term-send-input) - (define-key term-mode-map "\C-d" 'term-delchar-or-maybe-eof) - (define-key term-mode-map "\C-c\C-a" 'term-bol) - (define-key term-mode-map "\C-c\C-u" 'term-kill-input) - (define-key term-mode-map "\C-c\C-w" 'backward-kill-word) - (define-key term-mode-map "\C-c\C-c" 'term-interrupt-subjob) - (define-key term-mode-map "\C-c\C-z" 'term-stop-subjob) - (define-key term-mode-map "\C-c\C-\\" 'term-quit-subjob) - (define-key term-mode-map "\C-c\C-m" 'term-copy-old-input) - (define-key term-mode-map "\C-c\C-o" 'term-kill-output) - (define-key term-mode-map "\C-c\C-r" 'term-show-output) - (define-key term-mode-map "\C-c\C-e" 'term-show-maximum-output) - (define-key term-mode-map "\C-c\C-l" 'term-dynamic-list-input-ring) - (define-key term-mode-map "\C-c\C-n" 'term-next-prompt) - (define-key term-mode-map "\C-c\C-p" 'term-previous-prompt) - (define-key term-mode-map "\C-c\C-d" 'term-send-eof) - (define-key term-mode-map "\C-c\C-k" 'term-char-mode) - (define-key term-mode-map "\C-c\C-j" 'term-line-mode) - (define-key term-mode-map "\C-c\C-q" 'term-pager-toggle) - - (copy-face 'default 'term-underline-face) - (set-face-underline-p 'term-underline-face t) - -; ;; completion: -; (define-key term-mode-map [menu-bar completion] -; (cons "Complete" (make-sparse-keymap "Complete"))) -; (define-key term-mode-map [menu-bar completion complete-expand] -; '("Expand File Name" . term-replace-by-expanded-filename)) -; (define-key term-mode-map [menu-bar completion complete-listing] -; '("File Completion Listing" . term-dynamic-list-filename-completions)) -; (define-key term-mode-map [menu-bar completion complete-file] -; '("Complete File Name" . term-dynamic-complete-filename)) -; (define-key term-mode-map [menu-bar completion complete] -; '("Complete Before Point" . term-dynamic-complete)) -; ;; Put them in the menu bar: -; (setq menu-bar-final-items (append '(terminal completion inout signals) -; menu-bar-final-items)) - ) - -;; Menu bars: -(term-ifnot-xemacs - (term-if-emacs19 - - ;; terminal: - (let (newmap) - (setq newmap (make-sparse-keymap "Terminal")) - (define-key newmap [terminal-pager-enable] - '("Enable paging" . term-fake-pager-enable)) - (define-key newmap [terminal-pager-disable] - '("Disable paging" . term-fake-pager-disable)) - (define-key newmap [terminal-char-mode] - '("Character mode" . term-char-mode)) - (define-key newmap [terminal-line-mode] - '("Line mode" . term-line-mode)) - (define-key newmap [menu-bar terminal] - (setq term-terminal-menu (cons "Terminal" newmap))) - - ;; completion: (line mode only) - (defvar term-completion-menu (make-sparse-keymap "Complete")) - (define-key term-mode-map [menu-bar completion] - (cons "Complete" term-completion-menu)) - (define-key term-completion-menu [complete-expand] - '("Expand File Name" . term-replace-by-expanded-filename)) - (define-key term-completion-menu [complete-listing] - '("File Completion Listing" . term-dynamic-list-filename-completions)) - (define-key term-completion-menu [menu-bar completion complete-file] - '("Complete File Name" . term-dynamic-complete-filename)) - (define-key term-completion-menu [menu-bar completion complete] - '("Complete Before Point" . term-dynamic-complete)) - - ;; Input history: (line mode only) - (defvar term-inout-menu (make-sparse-keymap "In/Out")) - (define-key term-mode-map [menu-bar inout] - (cons "In/Out" term-inout-menu)) - (define-key term-inout-menu [kill-output] - '("Kill Current Output Group" . term-kill-output)) - (define-key term-inout-menu [next-prompt] - '("Forward Output Group" . term-next-prompt)) - (define-key term-inout-menu [previous-prompt] - '("Backward Output Group" . term-previous-prompt)) - (define-key term-inout-menu [show-maximum-output] - '("Show Maximum Output" . term-show-maximum-output)) - (define-key term-inout-menu [show-output] - '("Show Current Output Group" . term-show-output)) - (define-key term-inout-menu [kill-input] - '("Kill Current Input" . term-kill-input)) - (define-key term-inout-menu [copy-input] - '("Copy Old Input" . term-copy-old-input)) - (define-key term-inout-menu [forward-matching-history] - '("Forward Matching Input..." . term-forward-matching-input)) - (define-key term-inout-menu [backward-matching-history] - '("Backward Matching Input..." . term-backward-matching-input)) - (define-key term-inout-menu [next-matching-history] - '("Next Matching Input..." . term-next-matching-input)) - (define-key term-inout-menu [previous-matching-history] - '("Previous Matching Input..." . term-previous-matching-input)) - (define-key term-inout-menu [next-matching-history-from-input] - '("Next Matching Current Input" . term-next-matching-input-from-input)) - (define-key term-inout-menu [previous-matching-history-from-input] - '("Previous Matching Current Input" . term-previous-matching-input-from-input)) - (define-key term-inout-menu [next-history] - '("Next Input" . term-next-input)) - (define-key term-inout-menu [previous-history] - '("Previous Input" . term-previous-input)) - (define-key term-inout-menu [list-history] - '("List Input History" . term-dynamic-list-input-ring)) - (define-key term-inout-menu [expand-history] - '("Expand History Before Point" . term-replace-by-expanded-history)) - - ;; Signals - (setq newmap (make-sparse-keymap "Signals")) - (define-key newmap [eof] '("EOF" . term-send-eof)) - (define-key newmap [kill] '("KILL" . term-kill-subjob)) - (define-key newmap [quit] '("QUIT" . term-quit-subjob)) - (define-key newmap [cont] '("CONT" . term-continue-subjob)) - (define-key newmap [stop] '("STOP" . term-stop-subjob)) - (define-key newmap [] '("BREAK" . term-interrupt-subjob)) - (define-key term-mode-map [menu-bar signals] - (setq term-signals-menu (cons "Signals" newmap))) - ))) - -(defun term-reset-size (height width) - (setq term-height height) - (setq term-width width) - (setq term-start-line-column nil) - (setq term-current-row nil) - (setq term-current-column nil) - (term-scroll-region 0 height)) - -;; Recursive routine used to check if any string in term-kill-echo-list -;; matches part of the buffer before point. -;; If so, delete that matched part of the buffer - this suppresses echo. -;; Also, remove that string from the term-kill-echo-list. -;; We *also* remove any older string on the list, as a sanity measure, -;; in case something gets out of sync. (Except for type-ahead, there -;; should only be one element in the list.) - -(defun term-check-kill-echo-list () - (let ((cur term-kill-echo-list) (found nil) (save-point (point))) - (unwind-protect - (progn - (end-of-line) - (while cur - (let* ((str (car cur)) (len (length str)) (start (- (point) len))) - (if (and (>= start (point-min)) - (string= str (buffer-substring start (point)))) - (progn (delete-backward-char len) - (setq term-kill-echo-list (cdr cur)) - (setq term-current-column nil) - (setq term-current-row nil) - (setq term-start-line-column nil) - (setq cur nil found t)) - (setq cur (cdr cur)))))) - (if (not found) - (goto-char save-point))) - found)) - -(defun term-check-size (process) - (if (or (/= term-height (1- (window-displayed-height))) - (/= term-width (1- (window-width)))) - (progn - (term-reset-size (1- (window-displayed-height)) (1- (window-width))) - (set-process-window-size process term-height term-width)))) - -(defun term-send-raw-string (chars) - (let ((proc (get-buffer-process (current-buffer)))) - (if (not proc) - (error "Current buffer has no process") - ;; Note that (term-current-row) must be called *after* - ;; (point) has been updated to (process-mark proc). - (goto-char (process-mark proc)) - (if (term-pager-enabled) - (setq term-pager-count (term-current-row))) - (process-send-string proc chars)))) - -(defun term-send-raw () - "Send the last character typed through the terminal-emulator -without any interpretation." - (interactive) - - (term-if-xemacs - (if (key-press-event-p last-input-event) - (let ((mods (event-modifiers last-input-event)) - (key (event-key last-input-event)) - meta) - (if (memq 'meta mods) - (progn - (setq meta t) - (setq mods (delq 'meta mods)))) - (let ((ascii (event-to-character (character-to-event - (append mods (list key))) - t ;; lenient - nil ;; no meta mucking - t ;; allow non-ASCII - ))) - (cond (ascii - (if meta - (term-send-raw-string (format "\e%c" ascii)) - (term-send-raw-string (make-string 1 ascii)))) - (t (command-execute (key-binding last-input-event)))))) - (let ((cmd (lookup-key (current-global-map) (this-command-keys)))) - (and cmd (call-interactively cmd))))) - - (term-ifnot-xemacs - ;; Convert `return' to C-m, etc. - (if (and (symbolp last-input-char) - (get last-input-char 'ascii-character)) - (setq last-input-char (get last-input-char 'ascii-character))) - (term-send-raw-string (make-string 1 last-input-char)))) - -(defun term-mouse-paste (click arg) - "Insert the last stretch of killed text at the position clicked on." - (interactive "e\nP") - (term-if-xemacs - (term-send-raw-string (or (condition-case () (x-get-selection) (error ())) - (x-get-cutbuffer) - (error "No selection or cut buffer available")))) - (term-ifnot-xemacs - ;; Give temporary modes such as isearch a chance to turn off. - (run-hooks 'mouse-leave-buffer-hook) - (setq this-command 'yank) - (term-send-raw-string (current-kill (cond - ((listp arg) 0) - ((eq arg '-) -1) - (t (1- arg))))))) - -;; Which would be better: "\e[A" or "\eOA"? readline accepts either. -;; Both xterm and dtterm (CDE) send "\e[A", which argues for that choice. -;; The xterm termcap claims ku=\EOA; the dtterm terminfo entry says ku=\E[A. -(defun term-send-up () (interactive) (term-send-raw-string "\e[A")) -(defun term-send-down () (interactive) (term-send-raw-string "\e[B")) -(defun term-send-right () (interactive) (term-send-raw-string "\e[C")) -(defun term-send-left () (interactive) (term-send-raw-string "\e[D")) -(defun term-send-home () (interactive) (term-send-raw-string "\e[H")) -(defun term-send-end () (interactive) (term-send-raw-string "\eOw")) -(defun term-send-prior () (interactive) (term-send-raw-string "\e[5~")) -(defun term-send-next () (interactive) (term-send-raw-string "\e[6~")) -(defun term-send-del () (interactive) (term-send-raw-string "\C-?")) -(defun term-send-backspace () (interactive) (term-send-raw-string "\C-H")) - -(defun term-set-escape-char (c) - "Change term-escape-char and keymaps that depend on it." - (if term-escape-char - (define-key term-raw-map term-escape-char 'term-send-raw)) - (setq c (make-string 1 c)) - (define-key term-raw-map c term-raw-escape-map) - ;; Define standard bindings in term-raw-escape-map - (define-key term-raw-escape-map "\C-x" - (lookup-key (current-global-map) "\C-x")) - (define-key term-raw-escape-map "\C-v" - (lookup-key (current-global-map) "\C-v")) - (define-key term-raw-escape-map "\C-u" - (lookup-key (current-global-map) "\C-u")) - (define-key term-raw-escape-map c 'term-send-raw) - (define-key term-raw-escape-map "\C-q" 'term-pager-toggle) - ;; The keybinding for term-char-mode is needed by the menubar code. - (define-key term-raw-escape-map "\C-k" 'term-char-mode) - (define-key term-raw-escape-map "\C-j" 'term-line-mode)) - -(defun term-char-mode () - "Switch to char (\"raw\") sub-mode of term mode. -Each character you type is sent directly to the inferior without -intervention from emacs, except for the escape character (usually C-c)." - (interactive) - (if (not term-raw-map) - ;; Initialize term-raw-map. - (let* ((map (make-keymap)) - (save-meta-prefix-char meta-prefix-char) - (i 0)) - ;; Temporarily disable meta-prefix-char while building keymaps. - (setq meta-prefix-char -1) - (term-if-xemacs - (set-keymap-default-binding map 'term-send-raw)) - (term-ifnot-xemacs - (while (< i 128) - (define-key map (make-string 1 i) 'term-send-raw) - (setq i (1+ i)))) - (setq term-raw-map map) - (setq term-raw-escape-map - (copy-keymap (lookup-key (current-global-map) "\C-x"))) - (define-key term-raw-map [up] 'term-send-up) - (define-key term-raw-map [down] 'term-send-down) - (define-key term-raw-map [right] 'term-send-right) - (define-key term-raw-map [left] 'term-send-left) - (define-key term-raw-map [home] 'term-send-home) - (define-key term-raw-map [end] 'term-send-end) - (define-key term-raw-map [prior] 'term-send-prior) - (define-key term-raw-map [next] 'term-send-next) - (term-if-xemacs - (define-key term-raw-map [button2] 'term-mouse-paste)) - (term-ifnot-xemacs - (define-key term-raw-map [mouse-2] 'term-mouse-paste) - (define-key term-raw-map [menu-bar terminal] term-terminal-menu) - (define-key term-raw-map [menu-bar signals] term-signals-menu) - (define-key term-raw-map [delete] 'term-send-del) - (define-key term-raw-map [backspace] 'term-send-backspace)) - (setq meta-prefix-char save-meta-prefix-char) - (term-set-escape-char ?\C-c))) - ;; FIXME: Emit message? Cfr ilisp-raw-message - (if (term-in-line-mode) - (progn - (setq term-old-mode-map (current-local-map)) - (use-local-map term-raw-map) - - ;; Send existing partial line to inferior (without newline). - (let ((pmark (process-mark (get-buffer-process (current-buffer)))) - (save-input-sender term-input-sender)) - (if (> (point) pmark) - (unwind-protect - (progn - (setq term-input-sender - (symbol-function 'term-send-string)) - (end-of-line) - (term-send-input)) - (setq term-input-sender save-input-sender)))) - (term-update-mode-line)))) - -(defun term-line-mode () - "Switch to line (\"cooked\") sub-mode of term mode. -This means that emacs editing commands work as normally, until -you type \\[term-send-input] which sends the current line to the inferior." - (interactive) - (if (term-in-char-mode) - (progn - (use-local-map term-old-mode-map) - (term-update-mode-line)))) - -(defun term-update-mode-line () - (setq mode-line-process - (if (term-in-char-mode) - (if (term-pager-enabled) '(": char page %s") '(": char %s")) - (if (term-pager-enabled) '(": line page %s") '(": line %s")))) - (force-mode-line-update)) - -(defun term-check-proc (buffer) - "True if there is a process associated w/buffer BUFFER, and -it is alive (status RUN or STOP). BUFFER can be either a buffer or the -name of one" - (let ((proc (get-buffer-process buffer))) - (and proc (memq (process-status proc) '(run stop))))) - -;;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it () -;;; for the second argument (program). -;;;###autoload -(defun make-term (name program &optional startfile &rest switches) - "Make a term process NAME in a buffer, running PROGRAM. -The name of the buffer is made by surrounding NAME with `*'s. -If there is already a running process in that buffer, it is not restarted. -Optional third arg STARTFILE is the name of a file to send the contents of to -the process. Any more args are arguments to PROGRAM." - (let ((buffer (get-buffer-create (concat "*" name "*")))) - ;; If no process, or nuked process, crank up a new one and put buffer in - ;; term mode. Otherwise, leave buffer and existing process alone. - (cond ((not (term-check-proc buffer)) - (save-excursion - (set-buffer buffer) - (term-mode)) ; Install local vars, mode, keymap, ... - (term-exec buffer name program startfile switches))) - buffer)) - -;;;###autoload -(defun term (program) - "Start a terminal-emulator in a new buffer." - (interactive (list (read-from-minibuffer "Run program: " - (or explicit-shell-file-name - (getenv "ESHELL") - (getenv "SHELL") - "/bin/sh")))) - (set-buffer (make-term "terminal" program)) - (term-mode) - (term-char-mode) - (switch-to-buffer "*terminal*")) - -(defun term-exec (buffer name command startfile switches) - "Start up a process in buffer for term modes. -Blasts any old process running in the buffer. Doesn't set the buffer mode. -You can use this to cheaply run a series of processes in the same term -buffer. The hook term-exec-hook is run after each exec." - (save-excursion - (set-buffer buffer) - (let ((proc (get-buffer-process buffer))) ; Blast any old process. - (if proc (delete-process proc))) - ;; Crank up a new process - (let ((proc (term-exec-1 name buffer command switches))) - (make-local-variable 'term-ptyp) - (setq term-ptyp process-connection-type) ; T if pty, NIL if pipe. - ;; Jump to the end, and set the process mark. - (goto-char (point-max)) - (set-marker (process-mark proc) (point)) - (set-process-filter proc 'term-emulate-terminal) - ;; Feed it the startfile. - (cond (startfile - ;;This is guaranteed to wait long enough - ;;but has bad results if the term does not prompt at all - ;; (while (= size (buffer-size)) - ;; (sleep-for 1)) - ;;I hope 1 second is enough! - (sleep-for 1) - (goto-char (point-max)) - (insert-file-contents startfile) - (setq startfile (buffer-substring (point) (point-max))) - (delete-region (point) (point-max)) - (term-send-string proc startfile))) - (run-hooks 'term-exec-hook) - buffer))) - -;;; Name to use for TERM. -;;; Using "emacs" loses, because bash disables editing if TERM == emacs. -(defvar term-term-name "eterm") -; Format string, usage: (format term-termcap-string emacs-term-name "TERMCAP=" 24 80) -(defvar term-termcap-format - "%s%s:li#%d:co#%d:cl=\\E[H\\E[J:cd=\\E[J:bs:am:xn:cm=\\E[%%i%%d;%%dH\ -:nd=\\E[C:up=\\E[A:ce=\\E[K:ho=\\E[H:pt\ -:al=\\E[L:dl=\\E[M:DL=\\E[%%dM:AL=\\E[%%dL:cs=\\E[%%i%%d;%%dr:sf=\\n\ -:te=\\E[2J\\E[?47l\\E8:ti=\\E7\\E[?47h\ -:dc=\\E[P:DC=\\E[%%dP:IC=\\E[%%d@:im=\\E[4h:ei=\\E[4l:mi\ -:kd=\\E[B:kl=\\E[D:kr=\\E[C:ku=\\E[A\ -:so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:md=\\E[1m:mr=\\E[7m:me=\\E[m\ -:UP=\\E[%%dA:DO=\\E[%%dB:LE=\\E[%%dD:RI=\\E[%%dC" -;;; : -undefine ic - "termcap capabilities supported") - -;;; This auxiliary function cranks up the process for term-exec in -;;; the appropriate environment. - -(defun term-exec-1 (name buffer command switches) - ;; We need to do an extra (fork-less) exec to run stty. - ;; (This would not be needed if we had suitable emacs primitives.) - ;; The 'if ...; then shift; fi' hack is because Bourne shell - ;; loses one arg when called with -c, and newer shells (bash, ksh) don't. - ;; Thus we add an extra dummy argument "..", and then remove it. - (let ((process-environment - (nconc - (list - (format "TERM=%s" term-term-name) - (if (and (boundp 'system-uses-terminfo) system-uses-terminfo) - (format "TERMINFO=%s" data-directory) - (format term-termcap-format "TERMCAP=" - term-term-name term-height term-width)) - (format "EMACS=%s (term:%s)" emacs-version term-protocol-version) - (format "LINES=%d" term-height) - (format "COLUMNS=%d" term-width)) - process-environment))) - (apply 'start-process name buffer - "/bin/sh" "-c" - (format "stty -nl echo rows %d columns %d sane 2>/dev/null;\ -if [ $1 = .. ]; then shift; fi; exec \"$@\"" - term-height term-width) - ".." - command switches))) - -;;; This should be in emacs, but it isn't. -(defun term-mem (item list &optional elt=) - "Test to see if ITEM is equal to an item in LIST. -Option comparison function ELT= defaults to equal." - (let ((elt= (or elt= (function equal))) - (done nil)) - (while (and list (not done)) - (if (funcall elt= item (car list)) - (setq done list) - (setq list (cdr list)))) - done)) - - -;;; Input history processing in a buffer -;;; =========================================================================== -;;; Useful input history functions, courtesy of the Ergo group. - -;;; Eleven commands: -;;; term-dynamic-list-input-ring List history in help buffer. -;;; term-previous-input Previous input... -;;; term-previous-matching-input ...matching a string. -;;; term-previous-matching-input-from-input ... matching the current input. -;;; term-next-input Next input... -;;; term-next-matching-input ...matching a string. -;;; term-next-matching-input-from-input ... matching the current input. -;;; term-backward-matching-input Backwards input... -;;; term-forward-matching-input ...matching a string. -;;; term-replace-by-expanded-history Expand history at point; -;;; replace with expanded history. -;;; term-magic-space Expand history and insert space. -;;; -;;; Three functions: -;;; term-read-input-ring Read into term-input-ring... -;;; term-write-input-ring Write to term-input-ring-file-name. -;;; term-replace-by-expanded-history-before-point Workhorse function. - -(defun term-read-input-ring (&optional silent) - "Sets the buffer's `term-input-ring' from a history file. -The name of the file is given by the variable `term-input-ring-file-name'. -The history ring is of size `term-input-ring-size', regardless of file size. -If `term-input-ring-file-name' is nil this function does nothing. - -If the optional argument SILENT is non-nil, we say nothing about a -failure to read the history file. - -This function is useful for major mode commands and mode hooks. - -The structure of the history file should be one input command per line, -with the most recent command last. -See also `term-input-ignoredups' and `term-write-input-ring'." - (cond ((or (null term-input-ring-file-name) - (equal term-input-ring-file-name "")) - nil) - ((not (file-readable-p term-input-ring-file-name)) - (or silent - (message "Cannot read history file %s" - term-input-ring-file-name))) - (t - (let ((history-buf (get-buffer-create " *temp*")) - (file term-input-ring-file-name) - (count 0) - (ring (make-ring term-input-ring-size))) - (unwind-protect - (save-excursion - (set-buffer history-buf) - (widen) - (erase-buffer) - (insert-file-contents file) - ;; Save restriction in case file is already visited... - ;; Watch for those date stamps in history files! - (goto-char (point-max)) - (while (and (< count term-input-ring-size) - (re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$" - nil t)) - (let ((history (buffer-substring (match-beginning 1) - (match-end 1)))) - (if (or (null term-input-ignoredups) - (ring-empty-p ring) - (not (string-equal (ring-ref ring 0) history))) - (ring-insert-at-beginning ring history))) - (setq count (1+ count)))) - (kill-buffer history-buf)) - (setq term-input-ring ring - term-input-ring-index nil))))) - -(defun term-write-input-ring () - "Writes the buffer's `term-input-ring' to a history file. -The name of the file is given by the variable `term-input-ring-file-name'. -The original contents of the file are lost if `term-input-ring' is not empty. -If `term-input-ring-file-name' is nil this function does nothing. - -Useful within process sentinels. - -See also `term-read-input-ring'." - (cond ((or (null term-input-ring-file-name) - (equal term-input-ring-file-name "") - (null term-input-ring) (ring-empty-p term-input-ring)) - nil) - ((not (file-writable-p term-input-ring-file-name)) - (message "Cannot write history file %s" term-input-ring-file-name)) - (t - (let* ((history-buf (get-buffer-create " *Temp Input History*")) - (ring term-input-ring) - (file term-input-ring-file-name) - (index (ring-length ring))) - ;; Write it all out into a buffer first. Much faster, but messier, - ;; than writing it one line at a time. - (save-excursion - (set-buffer history-buf) - (erase-buffer) - (while (> index 0) - (setq index (1- index)) - (insert (ring-ref ring index) ?\n)) - (write-region (buffer-string) nil file nil 'no-message) - (kill-buffer nil)))))) - - -(defun term-dynamic-list-input-ring () - "List in help buffer the buffer's input history." - (interactive) - (if (or (not (ring-p term-input-ring)) - (ring-empty-p term-input-ring)) - (message "No history") - (let ((history nil) - (history-buffer " *Input History*") - (index (1- (ring-length term-input-ring))) - (conf (current-window-configuration))) - ;; We have to build up a list ourselves from the ring vector. - (while (>= index 0) - (setq history (cons (ring-ref term-input-ring index) history) - index (1- index))) - ;; Change "completion" to "history reference" - ;; to make the display accurate. - (with-output-to-temp-buffer history-buffer - (display-completion-list history) - (set-buffer history-buffer) - (forward-line 3) - (while (search-backward "completion" nil 'move) - (replace-match "history reference"))) - (sit-for 0) - (message "Hit space to flush") - (let ((ch (read-event))) - (if (eq ch ?\ ) - (set-window-configuration conf) - (setq unread-command-events (list ch))))))) - - -(defun term-regexp-arg (prompt) - ;; Return list of regexp and prefix arg using PROMPT. - (let* ((minibuffer-history-sexp-flag nil) - ;; Don't clobber this. - (last-command last-command) - (regexp (read-from-minibuffer prompt nil nil nil - 'minibuffer-history-search-history))) - (list (if (string-equal regexp "") - (setcar minibuffer-history-search-history - (nth 1 minibuffer-history-search-history)) - regexp) - (prefix-numeric-value current-prefix-arg)))) - -(defun term-search-arg (arg) - ;; First make sure there is a ring and that we are after the process mark - (cond ((not (term-after-pmark-p)) - (error "Not at command line")) - ((or (null term-input-ring) - (ring-empty-p term-input-ring)) - (error "Empty input ring")) - ((zerop arg) - ;; arg of zero resets search from beginning, and uses arg of 1 - (setq term-input-ring-index nil) - 1) - (t - arg))) - -(defun term-search-start (arg) - ;; Index to start a directional search, starting at term-input-ring-index - (if term-input-ring-index - ;; If a search is running, offset by 1 in direction of arg - (mod (+ term-input-ring-index (if (> arg 0) 1 -1)) - (ring-length term-input-ring)) - ;; For a new search, start from beginning or end, as appropriate - (if (>= arg 0) - 0 ; First elt for forward search - (1- (ring-length term-input-ring))))) ; Last elt for backward search - -(defun term-previous-input-string (arg) - "Return the string ARG places along the input ring. -Moves relative to `term-input-ring-index'." - (ring-ref term-input-ring (if term-input-ring-index - (mod (+ arg term-input-ring-index) - (ring-length term-input-ring)) - arg))) - -(defun term-previous-input (arg) - "Cycle backwards through input history." - (interactive "*p") - (term-previous-matching-input "." arg)) - -(defun term-next-input (arg) - "Cycle forwards through input history." - (interactive "*p") - (term-previous-input (- arg))) - -(defun term-previous-matching-input-string (regexp arg) - "Return the string matching REGEXP ARG places along the input ring. -Moves relative to `term-input-ring-index'." - (let* ((pos (term-previous-matching-input-string-position regexp arg))) - (if pos (ring-ref term-input-ring pos)))) - -(defun term-previous-matching-input-string-position (regexp arg &optional start) - "Return the index matching REGEXP ARG places along the input ring. -Moves relative to START, or `term-input-ring-index'." - (if (or (not (ring-p term-input-ring)) - (ring-empty-p term-input-ring)) - (error "No history")) - (let* ((len (ring-length term-input-ring)) - (motion (if (> arg 0) 1 -1)) - (n (mod (- (or start (term-search-start arg)) motion) len)) - (tried-each-ring-item nil) - (prev nil)) - ;; Do the whole search as many times as the argument says. - (while (and (/= arg 0) (not tried-each-ring-item)) - ;; Step once. - (setq prev n - n (mod (+ n motion) len)) - ;; If we haven't reached a match, step some more. - (while (and (< n len) (not tried-each-ring-item) - (not (string-match regexp (ring-ref term-input-ring n)))) - (setq n (mod (+ n motion) len) - ;; If we have gone all the way around in this search. - tried-each-ring-item (= n prev))) - (setq arg (if (> arg 0) (1- arg) (1+ arg)))) - ;; Now that we know which ring element to use, if we found it, return that. - (if (string-match regexp (ring-ref term-input-ring n)) - n))) - -(defun term-previous-matching-input (regexp arg) - "Search backwards through input history for match for REGEXP. -\(Previous history elements are earlier commands.) -With prefix argument N, search for Nth previous match. -If N is negative, find the next or Nth next match." - (interactive (term-regexp-arg "Previous input matching (regexp): ")) - (setq arg (term-search-arg arg)) - (let ((pos (term-previous-matching-input-string-position regexp arg))) - ;; Has a match been found? - (if (null pos) - (error "Not found") - (setq term-input-ring-index pos) - (message "History item: %d" (1+ pos)) - (delete-region - ;; Can't use kill-region as it sets this-command - (process-mark (get-buffer-process (current-buffer))) (point)) - (insert (ring-ref term-input-ring pos))))) - -(defun term-next-matching-input (regexp arg) - "Search forwards through input history for match for REGEXP. -\(Later history elements are more recent commands.) -With prefix argument N, search for Nth following match. -If N is negative, find the previous or Nth previous match." - (interactive (term-regexp-arg "Next input matching (regexp): ")) - (term-previous-matching-input regexp (- arg))) - -(defun term-previous-matching-input-from-input (arg) - "Search backwards through input history for match for current input. -\(Previous history elements are earlier commands.) -With prefix argument N, search for Nth previous match. -If N is negative, search forwards for the -Nth following match." - (interactive "p") - (if (not (memq last-command '(term-previous-matching-input-from-input - term-next-matching-input-from-input))) - ;; Starting a new search - (setq term-matching-input-from-input-string - (buffer-substring - (process-mark (get-buffer-process (current-buffer))) - (point)) - term-input-ring-index nil)) - (term-previous-matching-input - (concat "^" (regexp-quote term-matching-input-from-input-string)) - arg)) - -(defun term-next-matching-input-from-input (arg) - "Search forwards through input history for match for current input. -\(Following history elements are more recent commands.) -With prefix argument N, search for Nth following match. -If N is negative, search backwards for the -Nth previous match." - (interactive "p") - (term-previous-matching-input-from-input (- arg))) - - -(defun term-replace-by-expanded-history (&optional silent) - "Expand input command history references before point. -Expansion is dependent on the value of `term-input-autoexpand'. - -This function depends on the buffer's idea of the input history, which may not -match the command interpreter's idea, assuming it has one. - -Assumes history syntax is like typical Un*x shells'. However, since emacs -cannot know the interpreter's idea of input line numbers, assuming it has one, -it cannot expand absolute input line number references. - -If the optional argument SILENT is non-nil, never complain -even if history reference seems erroneous. - -See `term-magic-space' and `term-replace-by-expanded-history-before-point'. - -Returns t if successful." - (interactive) - (if (and term-input-autoexpand - (string-match "[!^]" (funcall term-get-old-input)) - (save-excursion (beginning-of-line) - (looking-at term-prompt-regexp))) - ;; Looks like there might be history references in the command. - (let ((previous-modified-tick (buffer-modified-tick))) - (message "Expanding history references...") - (term-replace-by-expanded-history-before-point silent) - (/= previous-modified-tick (buffer-modified-tick))))) - - -(defun term-replace-by-expanded-history-before-point (silent) - "Expand directory stack reference before point. -See `term-replace-by-expanded-history'. Returns t if successful." - (save-excursion - (let ((toend (- (save-excursion (end-of-line nil) (point)) (point))) - (start (progn (term-bol nil) (point)))) - (while (progn - (skip-chars-forward "^!^" - (save-excursion - (end-of-line nil) (- (point) toend))) - (< (point) - (save-excursion - (end-of-line nil) (- (point) toend)))) - ;; This seems a bit complex. We look for references such as !!, !-num, - ;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^. - ;; If that wasn't enough, the plings can be suffixed with argument - ;; range specifiers. - ;; Argument ranges are complex too, so we hive off the input line, - ;; referenced with plings, with the range string to `term-args'. - (setq term-input-ring-index nil) - (cond ((or (= (preceding-char) ?\\) - (term-within-quotes start (point))) - ;; The history is quoted, or we're in quotes. - (goto-char (1+ (point)))) - ((looking-at "![0-9]+\\($\\|[^-]\\)") - ;; We cannot know the interpreter's idea of input line numbers. - (goto-char (match-end 0)) - (message "Absolute reference cannot be expanded")) - ((looking-at "!-\\([0-9]+\\)\\(:?[0-9^$*-]+\\)?") - ;; Just a number of args from `number' lines backward. - (let ((number (1- (string-to-number - (buffer-substring (match-beginning 1) - (match-end 1)))))) - (if (<= number (ring-length term-input-ring)) - (progn - (replace-match - (term-args (term-previous-input-string number) - (match-beginning 2) (match-end 2)) - t t) - (setq term-input-ring-index number) - (message "History item: %d" (1+ number))) - (goto-char (match-end 0)) - (message "Relative reference exceeds input history size")))) - ((or (looking-at "!!?:?\\([0-9^$*-]+\\)") (looking-at "!!")) - ;; Just a number of args from the previous input line. - (replace-match - (term-args (term-previous-input-string 0) - (match-beginning 1) (match-end 1)) - t t) - (message "History item: previous")) - ((looking-at - "!\\??\\({\\(.+\\)}\\|\\(\\sw+\\)\\)\\(:?[0-9^$*-]+\\)?") - ;; Most recent input starting with or containing (possibly - ;; protected) string, maybe just a number of args. Phew. - (let* ((mb1 (match-beginning 1)) (me1 (match-end 1)) - (mb2 (match-beginning 2)) (me2 (match-end 2)) - (exp (buffer-substring (or mb2 mb1) (or me2 me1))) - (pref (if (save-match-data (looking-at "!\\?")) "" "^")) - (pos (save-match-data - (term-previous-matching-input-string-position - (concat pref (regexp-quote exp)) 1)))) - (if (null pos) - (progn - (goto-char (match-end 0)) - (or silent - (progn (message "Not found") - (ding)))) - (setq term-input-ring-index pos) - (replace-match - (term-args (ring-ref term-input-ring pos) - (match-beginning 4) (match-end 4)) - t t) - (message "History item: %d" (1+ pos))))) - ((looking-at "\\^\\([^^]+\\)\\^?\\([^^]*\\)\\^?") - ;; Quick substitution on the previous input line. - (let ((old (buffer-substring (match-beginning 1) (match-end 1))) - (new (buffer-substring (match-beginning 2) (match-end 2))) - (pos nil)) - (replace-match (term-previous-input-string 0) t t) - (setq pos (point)) - (goto-char (match-beginning 0)) - (if (not (search-forward old pos t)) - (or silent - (error "Not found")) - (replace-match new t t) - (message "History item: substituted")))) - (t - (goto-char (match-end 0)))))))) - - -(defun term-magic-space (arg) - "Expand input history references before point and insert ARG spaces. -A useful command to bind to SPC. See `term-replace-by-expanded-history'." - (interactive "p") - (term-replace-by-expanded-history) - (self-insert-command arg)) - -(defun term-within-quotes (beg end) - "Return t if the number of quotes between BEG and END is odd. -Quotes are single and double." - (let ((countsq (term-how-many-region "\\(^\\|[^\\\\]\\)\'" beg end)) - (countdq (term-how-many-region "\\(^\\|[^\\\\]\\)\"" beg end))) - (or (= (mod countsq 2) 1) (= (mod countdq 2) 1)))) - -(defun term-how-many-region (regexp beg end) - "Return number of matches for REGEXP from BEG to END." - (let ((count 0)) - (save-excursion - (save-match-data - (goto-char beg) - (while (re-search-forward regexp end t) - (setq count (1+ count))))) - count)) - -(defun term-args (string begin end) - ;; From STRING, return the args depending on the range specified in the text - ;; from BEGIN to END. If BEGIN is nil, assume all args. Ignore leading `:'. - ;; Range can be x-y, x-, -y, where x/y can be [0-9], *, ^, $. - (save-match-data - (if (null begin) - (term-arguments string 0 nil) - (let* ((range (buffer-substring - (if (eq (char-after begin) ?:) (1+ begin) begin) end)) - (nth (cond ((string-match "^[*^]" range) 1) - ((string-match "^-" range) 0) - ((string-equal range "$") nil) - (t (string-to-number range)))) - (mth (cond ((string-match "[-*$]$" range) nil) - ((string-match "-" range) - (string-to-number (substring range (match-end 0)))) - (t nth)))) - (term-arguments string nth mth))))) - -;; Return a list of arguments from ARG. Break it up at the -;; delimiters in term-delimiter-argument-list. Returned list is backwards. -(defun term-delim-arg (arg) - (if (null term-delimiter-argument-list) - (list arg) - (let ((args nil) - (pos 0) - (len (length arg))) - (while (< pos len) - (let ((char (aref arg pos)) - (start pos)) - (if (memq char term-delimiter-argument-list) - (while (and (< pos len) (eq (aref arg pos) char)) - (setq pos (1+ pos))) - (while (and (< pos len) - (not (memq (aref arg pos) - term-delimiter-argument-list))) - (setq pos (1+ pos)))) - (setq args (cons (substring arg start pos) args)))) - args))) - -(defun term-arguments (string nth mth) - "Return from STRING the NTH to MTH arguments. -NTH and/or MTH can be nil, which means the last argument. -Returned arguments are separated by single spaces. -We assume whitespace separates arguments, except within quotes. -Also, a run of one or more of a single character -in `term-delimiter-argument-list' is a separate argument. -Argument 0 is the command name." - (let ((argpart "[^ \n\t\"'`]+\\|\\(\"[^\"]*\"\\|'[^']*'\\|`[^`]*`\\)") - (args ()) (pos 0) - (count 0) - beg str quotes) - ;; Build a list of all the args until we have as many as we want. - (while (and (or (null mth) (<= count mth)) - (string-match argpart string pos)) - (if (and beg (= pos (match-beginning 0))) - ;; It's contiguous, part of the same arg. - (setq pos (match-end 0) - quotes (or quotes (match-beginning 1))) - ;; It's a new separate arg. - (if beg - ;; Put the previous arg, if there was one, onto ARGS. - (setq str (substring string beg pos) - args (if quotes (cons str args) - (nconc (term-delim-arg str) args)) - count (1+ count))) - (setq quotes (match-beginning 1)) - (setq beg (match-beginning 0)) - (setq pos (match-end 0)))) - (if beg - (setq str (substring string beg pos) - args (if quotes (cons str args) - (nconc (term-delim-arg str) args)) - count (1+ count))) - (let ((n (or nth (1- count))) - (m (if mth (1- (- count mth)) 0))) - (mapconcat - (function (lambda (a) a)) (nthcdr n (nreverse (nthcdr m args))) " ")))) - -;;; -;;; Input processing stuff [line mode] -;;; - -(defun term-send-input () - "Send input to process. -After the process output mark, sends all text from the process mark to -point as input to the process. Before the process output mark, calls value -of variable term-get-old-input to retrieve old input, copies it to the -process mark, and sends it. A terminal newline is also inserted into the -buffer and sent to the process. The list of function names contained in the -value of `term-input-filter-functions' is called on the input before sending -it. The input is entered into the input history ring, if the value of variable -term-input-filter returns non-nil when called on the input. - -Any history reference may be expanded depending on the value of the variable -`term-input-autoexpand'. The list of function names contained in the value -of `term-input-filter-functions' is called on the input before sending it. -The input is entered into the input history ring, if the value of variable -`term-input-filter' returns non-nil when called on the input. - -If variable `term-eol-on-send' is non-nil, then point is moved to the -end of line before sending the input. - -The values of `term-get-old-input', `term-input-filter-functions', and -`term-input-filter' are chosen according to the command interpreter running -in the buffer. E.g., - -If the interpreter is the csh, - term-get-old-input is the default: take the current line, discard any - initial string matching regexp term-prompt-regexp. - term-input-filter-functions monitors input for \"cd\", \"pushd\", and - \"popd\" commands. When it sees one, it cd's the buffer. - term-input-filter is the default: returns T if the input isn't all white - space. - -If the term is Lucid Common Lisp, - term-get-old-input snarfs the sexp ending at point. - term-input-filter-functions does nothing. - term-input-filter returns NIL if the input matches input-filter-regexp, - which matches (1) all whitespace (2) :a, :c, etc. - -Similarly for Soar, Scheme, etc." - (interactive) - ;; Note that the input string does not include its terminal newline. - (let ((proc (get-buffer-process (current-buffer)))) - (if (not proc) (error "Current buffer has no process") - (let* ((pmark (process-mark proc)) - (pmark-val (marker-position pmark)) - (input-is-new (>= (point) pmark-val)) - (intxt (if input-is-new - (progn (if term-eol-on-send (end-of-line)) - (buffer-substring pmark (point))) - (funcall term-get-old-input))) - (input (if (not (eq term-input-autoexpand 'input)) - ;; Just whatever's already there - intxt - ;; Expand and leave it visible in buffer - (term-replace-by-expanded-history t) - (buffer-substring pmark (point)))) - (history (if (not (eq term-input-autoexpand 'history)) - input - ;; This is messy 'cos ultimately the original - ;; functions used do insertion, rather than return - ;; strings. We have to expand, then insert back. - (term-replace-by-expanded-history t) - (let ((copy (buffer-substring pmark (point)))) - (delete-region pmark (point)) - (insert input) - copy)))) - (if (term-pager-enabled) - (save-excursion - (goto-char (process-mark proc)) - (setq term-pager-count (term-current-row)))) - (if (and (funcall term-input-filter history) - (or (null term-input-ignoredups) - (not (ring-p term-input-ring)) - (ring-empty-p term-input-ring) - (not (string-equal (ring-ref term-input-ring 0) - history)))) - (ring-insert term-input-ring history)) - (let ((functions term-input-filter-functions)) - (while functions - (funcall (car functions) (concat input "\n")) - (setq functions (cdr functions)))) - (setq term-input-ring-index nil) - - ;; Update the markers before we send the input - ;; in case we get output amidst sending the input. - (set-marker term-last-input-start pmark) - (set-marker term-last-input-end (point)) - (if input-is-new - (progn - ;; Set up to delete, because inferior should echo. - (if (marker-buffer term-pending-delete-marker) - (delete-region term-pending-delete-marker pmark)) - (set-marker term-pending-delete-marker pmark-val) - (set-marker (process-mark proc) (point)))) - (goto-char pmark) - (funcall term-input-sender proc input))))) - -(defun term-get-old-input-default () - "Default for term-get-old-input. -Take the current line, and discard any initial text matching -term-prompt-regexp." - (save-excursion - (beginning-of-line) - (term-skip-prompt) - (let ((beg (point))) - (end-of-line) - (buffer-substring beg (point))))) - -(defun term-copy-old-input () - "Insert after prompt old input at point as new input to be edited. -Calls `term-get-old-input' to get old input." - (interactive) - (let ((input (funcall term-get-old-input)) - (process (get-buffer-process (current-buffer)))) - (if (not process) - (error "Current buffer has no process") - (goto-char (process-mark process)) - (insert input)))) - -(defun term-skip-prompt () - "Skip past the text matching regexp term-prompt-regexp. -If this takes us past the end of the current line, don't skip at all." - (let ((eol (save-excursion (end-of-line) (point)))) - (if (and (looking-at term-prompt-regexp) - (<= (match-end 0) eol)) - (goto-char (match-end 0))))) - - -(defun term-after-pmark-p () - "Is point after the process output marker?" - ;; Since output could come into the buffer after we looked at the point - ;; but before we looked at the process marker's value, we explicitly - ;; serialise. This is just because I don't know whether or not emacs - ;; services input during execution of lisp commands. - (let ((proc-pos (marker-position - (process-mark (get-buffer-process (current-buffer)))))) - (<= proc-pos (point)))) - -(defun term-simple-send (proc string) - "Default function for sending to PROC input STRING. -This just sends STRING plus a newline. To override this, -set the hook TERM-INPUT-SENDER." - (term-send-string proc string) - (term-send-string proc "\n")) - -(defun term-bol (arg) - "Goes to the beginning of line, then skips past the prompt, if any. -If a prefix argument is given (\\[universal-argument]), then no prompt skip --- go straight to column 0. - -The prompt skip is done by skipping text matching the regular expression -term-prompt-regexp, a buffer local variable." - (interactive "P") - (beginning-of-line) - (if (null arg) (term-skip-prompt))) - -;;; These two functions are for entering text you don't want echoed or -;;; saved -- typically passwords to ftp, telnet, or somesuch. -;;; Just enter m-x term-send-invisible and type in your line. - -(defun term-read-noecho (prompt &optional stars) - "Read a single line of text from user without echoing, and return it. -Prompt with argument PROMPT, a string. Optional argument STARS causes -input to be echoed with '*' characters on the prompt line. Input ends with -RET, LFD, or ESC. DEL or C-h rubs out. C-u kills line. C-g aborts (if -`inhibit-quit' is set because e.g. this function was called from a process -filter and C-g is pressed, this function returns nil rather than a string). - -Note that the keystrokes comprising the text can still be recovered -\(temporarily) with \\[view-lossage]. This may be a security bug for some -applications." - (let ((ans "") - (c 0) - (echo-keystrokes 0) - (cursor-in-echo-area t) - (done nil)) - (while (not done) - (if stars - (message "%s%s" prompt (make-string (length ans) ?*)) - (message "%s" prompt)) - (setq c (read-char)) - (cond ((= c ?\C-g) - ;; This function may get called from a process filter, where - ;; inhibit-quit is set. In later versions of emacs read-char - ;; may clear quit-flag itself and return C-g. That would make - ;; it impossible to quit this loop in a simple way, so - ;; re-enable it here (for backward-compatibility the check for - ;; quit-flag below would still be necessary, so this seems - ;; like the simplest way to do things). - (setq quit-flag t - done t)) - ((or (= c ?\r) (= c ?\n) (= c ?\e)) - (setq done t)) - ((= c ?\C-u) - (setq ans "")) - ((and (/= c ?\b) (/= c ?\177)) - (setq ans (concat ans (char-to-string c)))) - ((> (length ans) 0) - (setq ans (substring ans 0 -1))))) - (if quit-flag - ;; Emulate a true quit, except that we have to return a value. - (prog1 - (setq quit-flag nil) - (message "Quit") - (beep t)) - (message "") - ans))) - -(defun term-send-invisible (str &optional proc) - "Read a string without echoing. -Then send it to the process running in the current buffer. A new-line -is additionally sent. String is not saved on term input history list. -Security bug: your string can still be temporarily recovered with -\\[view-lossage]." - (interactive "P") ; Defeat snooping via C-x esc - (if (not (stringp str)) - (setq str (term-read-noecho "Non-echoed text: " t))) - (if (not proc) - (setq proc (get-buffer-process (current-buffer)))) - (if (not proc) (error "Current buffer has no process") - (setq term-kill-echo-list (nconc term-kill-echo-list - (cons str nil))) - (term-send-string proc str) - (term-send-string proc "\n"))) - - -;;; Low-level process communication - -(defvar term-input-chunk-size 512 - "*Long inputs send to term processes are broken up into chunks of this size. -If your process is choking on big inputs, try lowering the value.") - -(defun term-send-string (proc str) - "Send PROCESS the contents of STRING as input. -This is equivalent to process-send-string, except that long input strings -are broken up into chunks of size term-input-chunk-size. Processes -are given a chance to output between chunks. This can help prevent processes -from hanging when you send them long inputs on some OS's." - (let* ((len (length str)) - (i (min len term-input-chunk-size))) - (process-send-string proc (substring str 0 i)) - (while (< i len) - (let ((next-i (+ i term-input-chunk-size))) - (accept-process-output) - (process-send-string proc (substring str i (min len next-i))) - (setq i next-i))))) - -(defun term-send-region (proc start end) - "Sends to PROC the region delimited by START and END. -This is a replacement for process-send-region that tries to keep -your process from hanging on long inputs. See term-send-string." - (term-send-string proc (buffer-substring start end))) - - -;;; Random input hackage - -(defun term-kill-output () - "Kill all output from interpreter since last input." - (interactive) - (let ((pmark (process-mark (get-buffer-process (current-buffer))))) - (kill-region term-last-input-end pmark) - (goto-char pmark) - (insert "*** output flushed ***\n") - (set-marker pmark (point)))) - -(defun term-show-output () - "Display start of this batch of interpreter output at top of window. -Sets mark to the value of point when this command is run." - (interactive) - (goto-char term-last-input-end) - (backward-char) - (beginning-of-line) - (set-window-start (selected-window) (point)) - (end-of-line)) - -(defun term-interrupt-subjob () - "Interrupt the current subjob." - (interactive) - (interrupt-process nil term-ptyp)) - -(defun term-kill-subjob () - "Send kill signal to the current subjob." - (interactive) - (kill-process nil term-ptyp)) - -(defun term-quit-subjob () - "Send quit signal to the current subjob." - (interactive) - (quit-process nil term-ptyp)) - -(defun term-stop-subjob () - "Stop the current subjob. -WARNING: if there is no current subjob, you can end up suspending -the top-level process running in the buffer. If you accidentally do -this, use \\[term-continue-subjob] to resume the process. (This -is not a problem with most shells, since they ignore this signal.)" - (interactive) - (stop-process nil term-ptyp)) - -(defun term-continue-subjob () - "Send CONT signal to process buffer's process group. -Useful if you accidentally suspend the top-level process." - (interactive) - (continue-process nil term-ptyp)) - -(defun term-kill-input () - "Kill all text from last stuff output by interpreter to point." - (interactive) - (let* ((pmark (process-mark (get-buffer-process (current-buffer)))) - (p-pos (marker-position pmark))) - (if (> (point) p-pos) - (kill-region pmark (point))))) - -(defun term-delchar-or-maybe-eof (arg) - "Delete ARG characters forward, or send an EOF to process if at end of buffer." - (interactive "p") - (if (eobp) - (process-send-eof) - (delete-char arg))) - -(defun term-send-eof () - "Send an EOF to the current buffer's process." - (interactive) - (process-send-eof)) - -(defun term-backward-matching-input (regexp arg) - "Search backward through buffer for match for REGEXP. -Matches are searched for on lines that match `term-prompt-regexp'. -With prefix argument N, search for Nth previous match. -If N is negative, find the next or Nth next match." - (interactive (term-regexp-arg "Backward input matching (regexp): ")) - (let* ((re (concat term-prompt-regexp ".*" regexp)) - (pos (save-excursion (end-of-line (if (> arg 0) 0 1)) - (if (re-search-backward re nil t arg) - (point))))) - (if (null pos) - (progn (message "Not found") - (ding)) - (goto-char pos) - (term-bol nil)))) - -(defun term-forward-matching-input (regexp arg) - "Search forward through buffer for match for REGEXP. -Matches are searched for on lines that match `term-prompt-regexp'. -With prefix argument N, search for Nth following match. -If N is negative, find the previous or Nth previous match." - (interactive (term-regexp-arg "Forward input matching (regexp): ")) - (term-backward-matching-input regexp (- arg))) - - -(defun term-next-prompt (n) - "Move to end of Nth next prompt in the buffer. -See `term-prompt-regexp'." - (interactive "p") - (let ((paragraph-start term-prompt-regexp)) - (end-of-line (if (> n 0) 1 0)) - (forward-paragraph n) - (term-skip-prompt))) - -(defun term-previous-prompt (n) - "Move to end of Nth previous prompt in the buffer. -See `term-prompt-regexp'." - (interactive "p") - (term-next-prompt (- n))) - -;;; Support for source-file processing commands. -;;;============================================================================ -;;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have -;;; commands that process files of source text (e.g. loading or compiling -;;; files). So the corresponding process-in-a-buffer modes have commands -;;; for doing this (e.g., lisp-load-file). The functions below are useful -;;; for defining these commands. -;;; -;;; Alas, these guys don't do exactly the right thing for Lisp, Scheme -;;; and Soar, in that they don't know anything about file extensions. -;;; So the compile/load interface gets the wrong default occasionally. -;;; The load-file/compile-file default mechanism could be smarter -- it -;;; doesn't know about the relationship between filename extensions and -;;; whether the file is source or executable. If you compile foo.lisp -;;; with compile-file, then the next load-file should use foo.bin for -;;; the default, not foo.lisp. This is tricky to do right, particularly -;;; because the extension for executable files varies so much (.o, .bin, -;;; .lbin, .mo, .vo, .ao, ...). - - -;;; TERM-SOURCE-DEFAULT -- determines defaults for source-file processing -;;; commands. -;;; -;;; TERM-CHECK-SOURCE -- if FNAME is in a modified buffer, asks you if you -;;; want to save the buffer before issuing any process requests to the command -;;; interpreter. -;;; -;;; TERM-GET-SOURCE -- used by the source-file processing commands to prompt -;;; for the file to process. - -;;; (TERM-SOURCE-DEFAULT previous-dir/file source-modes) -;;;============================================================================ -;;; This function computes the defaults for the load-file and compile-file -;;; commands for tea, soar, cmulisp, and cmuscheme modes. -;;; -;;; - PREVIOUS-DIR/FILE is a pair (directory . filename) from the last -;;; source-file processing command. NIL if there hasn't been one yet. -;;; - SOURCE-MODES is a list used to determine what buffers contain source -;;; files: if the major mode of the buffer is in SOURCE-MODES, it's source. -;;; Typically, (lisp-mode) or (scheme-mode). -;;; -;;; If the command is given while the cursor is inside a string, *and* -;;; the string is an existing filename, *and* the filename is not a directory, -;;; then the string is taken as default. This allows you to just position -;;; your cursor over a string that's a filename and have it taken as default. -;;; -;;; If the command is given in a file buffer whose major mode is in -;;; SOURCE-MODES, then the filename is the default file, and the -;;; file's directory is the default directory. -;;; -;;; If the buffer isn't a source file buffer (e.g., it's the process buffer), -;;; then the default directory & file are what was used in the last source-file -;;; processing command (i.e., PREVIOUS-DIR/FILE). If this is the first time -;;; the command has been run (PREVIOUS-DIR/FILE is nil), the default directory -;;; is the cwd, with no default file. (\"no default file\" = nil) -;;; -;;; SOURCE-REGEXP is typically going to be something like (tea-mode) -;;; for T programs, (lisp-mode) for Lisp programs, (soar-mode lisp-mode) -;;; for Soar programs, etc. -;;; -;;; The function returns a pair: (default-directory . default-file). - -(defun term-source-default (previous-dir/file source-modes) - (cond ((and buffer-file-name (memq major-mode source-modes)) - (cons (file-name-directory buffer-file-name) - (file-name-nondirectory buffer-file-name))) - (previous-dir/file) - (t - (cons default-directory nil)))) - - -;;; (TERM-CHECK-SOURCE fname) -;;;============================================================================ -;;; Prior to loading or compiling (or otherwise processing) a file (in the CMU -;;; process-in-a-buffer modes), this function can be called on the filename. -;;; If the file is loaded into a buffer, and the buffer is modified, the user -;;; is queried to see if he wants to save the buffer before proceeding with -;;; the load or compile. - -(defun term-check-source (fname) - (let ((buff (get-file-buffer fname))) - (if (and buff - (buffer-modified-p buff) - (y-or-n-p (format "Save buffer %s first? " - (buffer-name buff)))) - ;; save BUFF. - (let ((old-buffer (current-buffer))) - (set-buffer buff) - (save-buffer) - (set-buffer old-buffer))))) - - -;;; (TERM-GET-SOURCE prompt prev-dir/file source-modes mustmatch-p) -;;;============================================================================ -;;; TERM-GET-SOURCE is used to prompt for filenames in command-interpreter -;;; commands that process source files (like loading or compiling a file). -;;; It prompts for the filename, provides a default, if there is one, -;;; and returns the result filename. -;;; -;;; See TERM-SOURCE-DEFAULT for more on determining defaults. -;;; -;;; PROMPT is the prompt string. PREV-DIR/FILE is the (directory . file) pair -;;; from the last source processing command. SOURCE-MODES is a list of major -;;; modes used to determine what file buffers contain source files. (These -;;; two arguments are used for determining defaults). If MUSTMATCH-P is true, -;;; then the filename reader will only accept a file that exists. -;;; -;;; A typical use: -;;; (interactive (term-get-source "Compile file: " prev-lisp-dir/file -;;; '(lisp-mode) t)) - -;;; This is pretty stupid about strings. It decides we're in a string -;;; if there's a quote on both sides of point on the current line. -(defun term-extract-string () - "Returns string around POINT that starts the current line or nil." - (save-excursion - (let* ((point (point)) - (bol (progn (beginning-of-line) (point))) - (eol (progn (end-of-line) (point))) - (start (progn (goto-char point) - (and (search-backward "\"" bol t) - (1+ (point))))) - (end (progn (goto-char point) - (and (search-forward "\"" eol t) - (1- (point)))))) - (and start end - (buffer-substring start end))))) - -(defun term-get-source (prompt prev-dir/file source-modes mustmatch-p) - (let* ((def (term-source-default prev-dir/file source-modes)) - (stringfile (term-extract-string)) - (sfile-p (and stringfile - (condition-case () - (file-exists-p stringfile) - (error nil)) - (not (file-directory-p stringfile)))) - (defdir (if sfile-p (file-name-directory stringfile) - (car def))) - (deffile (if sfile-p (file-name-nondirectory stringfile) - (cdr def))) - (ans (read-file-name (if deffile (format "%s(default %s) " - prompt deffile) - prompt) - defdir - (concat defdir deffile) - mustmatch-p))) - (list (expand-file-name (substitute-in-file-name ans))))) - -;;; I am somewhat divided on this string-default feature. It seems -;;; to violate the principle-of-least-astonishment, in that it makes -;;; the default harder to predict, so you actually have to look and see -;;; what the default really is before choosing it. This can trip you up. -;;; On the other hand, it can be useful, I guess. I would appreciate feedback -;;; on this. -;;; -Olin - - -;;; Simple process query facility. -;;; =========================================================================== -;;; This function is for commands that want to send a query to the process -;;; and show the response to the user. For example, a command to get the -;;; arglist for a Common Lisp function might send a "(arglist 'foo)" query -;;; to an inferior Common Lisp process. -;;; -;;; This simple facility just sends strings to the inferior process and pops -;;; up a window for the process buffer so you can see what the process -;;; responds with. We don't do anything fancy like try to intercept what the -;;; process responds with and put it in a pop-up window or on the message -;;; line. We just display the buffer. Low tech. Simple. Works good. - -;;; Send to the inferior process PROC the string STR. Pop-up but do not select -;;; a window for the inferior process so that its response can be seen. -(defun term-proc-query (proc str) - (let* ((proc-buf (process-buffer proc)) - (proc-mark (process-mark proc))) - (display-buffer proc-buf) - (set-buffer proc-buf) ; but it's not the selected *window* - (let ((proc-win (get-buffer-window proc-buf)) - (proc-pt (marker-position proc-mark))) - (term-send-string proc str) ; send the query - (accept-process-output proc) ; wait for some output - ;; Try to position the proc window so you can see the answer. - ;; This is bogus code. If you delete the (sit-for 0), it breaks. - ;; I don't know why. Wizards invited to improve it. - (if (not (pos-visible-in-window-p proc-pt proc-win)) - (let ((opoint (window-point proc-win))) - (set-window-point proc-win proc-mark) (sit-for 0) - (if (not (pos-visible-in-window-p opoint proc-win)) - (push-mark opoint) - (set-window-point proc-win opoint))))))) - -;;; Returns the current column in the current screen line. -;;; Note: (current-column) yields column in buffer line. - -(defun term-horizontal-column () - (- (term-current-column) (term-start-line-column))) - -;; Calls either vertical-motion or buffer-vertical-motion -(defmacro term-vertical-motion (count) - (list 'funcall 'term-vertical-motion count)) - -;; An emulation of vertical-motion that is independent of having a window. -;; Instead, it uses the term-width variable as the logical window width. - -(defun buffer-vertical-motion (count) - (cond ((= count 0) - (move-to-column (* term-width (/ (current-column) term-width))) - 0) - ((> count 0) - (let ((H) - (todo (+ count (/ (current-column) term-width)))) - (end-of-line) - ;; The loop iterates over buffer lines; - ;; H is the number of screen lines in the current line, i.e. - ;; the ceiling of dividing the buffer line width by term-width. - (while (and (<= (setq H (max (/ (+ (current-column) term-width -1) - term-width) - 1)) - todo) - (not (eobp))) - (setq todo (- todo H)) - (forward-char) ;; Move past the ?\n - (end-of-line)) ;; and on to the end of the next line. - (if (and (>= todo H) (> todo 0)) - (+ (- count todo) H -1) ;; Hit end of buffer. - (move-to-column (* todo term-width)) - count))) - (t ;; (< count 0) ;; Similar algorithm, but for upward motion. - (let ((H) - (todo (- count))) - (while (and (<= (setq H (max (/ (+ (current-column) term-width -1) - term-width) - 1)) - todo) - (progn (beginning-of-line) - (not (bobp)))) - (setq todo (- todo H)) - (backward-char)) ;; Move to end of previous line. - (if (and (>= todo H) (> todo 0)) - (+ count todo (- 1 H)) ;; Hit beginning of buffer. - (move-to-column (* (- H todo 1) term-width)) - count))))) - -;;; The term-start-line-column variable is used as a cache. -(defun term-start-line-column () - (cond (term-start-line-column) - ((let ((save-pos (point))) - (term-vertical-motion 0) - (setq term-start-line-column (current-column)) - (goto-char save-pos) - term-start-line-column)))) - -;;; Same as (current-column), but uses term-current-column as a cache. -(defun term-current-column () - (cond (term-current-column) - ((setq term-current-column (current-column))))) - -;;; Move DELTA column right (or left if delta < 0). - -(defun term-move-columns (delta) - (setq term-current-column (+ (term-current-column) delta)) - (move-to-column term-current-column t)) - -;; Insert COUNT copies of CHAR in the default face. -(defun term-insert-char (char count) - (let ((old-point (point))) - (insert-char char count) - (put-text-property old-point (point) 'face 'default))) - -(defun term-current-row () - (cond (term-current-row) - ((setq term-current-row - (save-restriction - (save-excursion - (narrow-to-region term-home-marker (point-max)) - (- (term-vertical-motion -9999)))))))) - -(defun term-adjust-current-row-cache (delta) - (if term-current-row - (setq term-current-row (+ term-current-row delta)))) - -(defun term-terminal-pos () - (save-excursion ; save-restriction - (let ((save-col (term-current-column)) - x y) - (term-vertical-motion 0) - (setq x (- save-col (current-column))) - (setq y (term-vertical-motion term-height)) - (cons x y)))) - -;;; Terminal emulation -;;; This is the standard process filter for term buffers. -;;; It emulates (most of the features of) a VT100/ANSI-style terminal. - -(defun term-emulate-terminal (proc str) - (let* ((previous-buffer (current-buffer)) - (i 0) char funny count save-point save-marker old-point temp win - (selected (selected-window)) - (str-length (length str))) - (unwind-protect - (progn - (set-buffer (process-buffer proc)) - - (if (marker-buffer term-pending-delete-marker) - (progn - ;; Delete text following term-pending-delete-marker. - (delete-region term-pending-delete-marker (process-mark proc)) - (set-marker term-pending-delete-marker nil))) - - (if (eq (window-buffer) (current-buffer)) - (progn - (setq term-vertical-motion (symbol-function 'vertical-motion)) - (term-check-size proc)) - (setq term-vertical-motion - (symbol-function 'buffer-vertical-motion))) - - (setq save-marker (copy-marker (process-mark proc))) - - (if (/= (point) (process-mark proc)) - (progn (setq save-point (point-marker)) - (goto-char (process-mark proc)))) - - (save-restriction - ;; If the buffer is in line mode, and there is a partial - ;; input line, save the line (by narrowing to leave it - ;; outside the restriction ) until we're done with output. - (if (and (> (point-max) (process-mark proc)) - (term-in-line-mode)) - (narrow-to-region (point-min) (process-mark proc))) - - (if term-log-buffer - (princ str term-log-buffer)) - (cond ((eq term-terminal-state 4) ;; Have saved pending output. - (setq str (concat term-terminal-parameter str)) - (setq term-terminal-parameter nil) - (setq str-length (length str)) - (setq term-terminal-state 0))) - - (while (< i str-length) - (setq char (aref str i)) - (cond ((< term-terminal-state 2) - ;; Look for prefix of regular chars - (setq funny - (string-match "[\r\n\000\007\033\t\b\032\016\017]" - str i)) - (if (not funny) (setq funny str-length)) - (cond ((> funny i) - (cond ((eq term-terminal-state 1) - (term-move-columns 1) - (setq term-terminal-state 0))) - (setq count (- funny i)) - (setq temp (- (+ (term-horizontal-column) count) - term-width)) - (cond ((<= temp 0)) ;; All count chars fit in line. - ((> count temp) ;; Some chars fit. - ;; This iteration, handle only what fits. - (setq count (- count temp)) - (setq funny (+ count i))) - ((or (not (or term-pager-count - term-scroll-with-delete)) - (> (term-handle-scroll 1) 0)) - (term-adjust-current-row-cache 1) - (setq count (min count term-width)) - (setq funny (+ count i)) - (setq term-start-line-column - term-current-column)) - (t ;; Doing PAGER processing. - (setq count 0 funny i) - (setq term-current-column nil) - (setq term-start-line-column nil))) - (setq old-point (point)) - ;; In the common case that we're at the end of - ;; the buffer, we can save a little work. - (cond ((/= (point) (point-max)) - (if term-insert-mode - ;; Inserting spaces, then deleting them, - ;; then inserting the actual text is - ;; inefficient, but it is simple, and - ;; the actual overhead is miniscule. - (term-insert-spaces count)) - (term-move-columns count) - (delete-region old-point (point))) - (t (setq term-current-column (+ (term-current-column) count)))) - (insert (substring str i funny)) - (put-text-property old-point (point) - 'face term-current-face) - ;; If the last char was written in last column, - ;; back up one column, but remember we did so. - ;; Thus we emulate xterm/vt100-style line-wrapping. - (cond ((eq temp 0) - (term-move-columns -1) - (setq term-terminal-state 1))) - (setq i (1- funny))) - ((and (setq term-terminal-state 0) - (eq char ?\^I)) ; TAB - ;; FIXME: Does not handle line wrap! - (setq count (term-current-column)) - (setq count (+ count 8 (- (mod count 8)))) - (if (< (move-to-column count nil) count) - (term-insert-char char 1)) - (setq term-current-column count)) - ((eq char ?\r) - ;; Optimize CRLF at end of buffer: - (cond ((and (< (setq temp (1+ i)) str-length) - (eq (aref str temp) ?\n) - (= (point) (point-max)) - (not (or term-pager-count - term-kill-echo-list - term-scroll-with-delete))) - (insert ?\n) - (term-adjust-current-row-cache 1) - (setq term-start-line-column 0) - (setq term-current-column 0) - (setq i temp)) - (t ;; Not followed by LF or can't optimize: - (term-vertical-motion 0) - (setq term-current-column term-start-line-column)))) - ((eq char ?\n) - (if (not (and term-kill-echo-list - (term-check-kill-echo-list))) - (term-down 1 t))) - ((eq char ?\b) - (term-move-columns -1)) - ((eq char ?\033) ; Escape - (setq term-terminal-state 2)) - ((eq char ?\0)) ; NUL: Do nothing - ((eq char ?\016)) ; Shift Out - ignored - ((eq char ?\017)) ; Shift In - ignored - ((eq char ?\^G) - (beep t)) ; Bell - ((eq char ?\032) - (let ((end (string-match "\n" str i))) - (if end - (progn (funcall term-command-hook - (substring str (1+ i) (1- end))) - (setq i end)) - (setq term-terminal-parameter - (substring str i)) - (setq term-terminal-state 4) - (setq i str-length)))) - (t ; insert char FIXME: Should never happen - (term-move-columns 1) - (backward-delete-char 1) - (insert char)))) - ((eq term-terminal-state 2) ; Seen Esc - (cond ((eq char ?\133) ;; ?\133 = ?[ - (make-local-variable 'term-terminal-parameter) - (make-local-variable 'term-terminal-previous-parameter) - (setq term-terminal-parameter 0) - (setq term-terminal-previous-parameter 0) - (setq term-terminal-state 3)) - ((eq char ?D) ;; scroll forward - (term-handle-deferred-scroll) - (term-down 1 t) - (setq term-terminal-state 0)) - ((eq char ?M) ;; scroll reversed - (term-insert-lines 1) - (setq term-terminal-state 0)) - ((eq char ?7) ;; Save cursor - (term-handle-deferred-scroll) - (setq term-saved-cursor - (cons (term-current-row) - (term-horizontal-column))) - (setq term-terminal-state 0)) - ((eq char ?8) ;; Restore cursor - (if term-saved-cursor - (term-goto (car term-saved-cursor) - (cdr term-saved-cursor))) - (setq term-terminal-state 0)) - ((setq term-terminal-state 0)))) - ((eq term-terminal-state 3) ; Seen Esc [ - (cond ((and (>= char ?0) (<= char ?9)) - (setq term-terminal-parameter - (+ (* 10 term-terminal-parameter) (- char ?0)))) - ((eq char ?\073 ) ; ?; - (setq term-terminal-previous-parameter - term-terminal-parameter) - (setq term-terminal-parameter 0)) - ((eq char ??)) ; Ignore ? - (t - (term-handle-ansi-escape proc char) - (setq term-terminal-state 0))))) - (if (term-handling-pager) - ;; Finish stuff to get ready to handle PAGER. - (progn - (if (> (% (current-column) term-width) 0) - (setq term-terminal-parameter - (substring str i)) - ;; We're at column 0. Goto end of buffer; to compensate, - ;; prepend a ?\r for later. This looks more consistent. - (if (zerop i) - (setq term-terminal-parameter - (concat "\r" (substring str i))) - (setq term-terminal-parameter (substring str (1- i))) - (aset term-terminal-parameter 0 ?\r)) - (goto-char (point-max))) - (setq term-terminal-state 4) - (make-local-variable 'term-pager-old-filter) - (setq term-pager-old-filter (process-filter proc)) - (set-process-filter proc term-pager-filter) - (setq i str-length))) - (setq i (1+ i)))) - - (if (>= (term-current-row) term-height) - (term-handle-deferred-scroll)) - - (set-marker (process-mark proc) (point)) - (if save-point - (progn (goto-char save-point) - (set-marker save-point nil))) - - ;; Check for a pending filename-and-line number to display. - ;; We do this before scrolling, because we might create a new window. - (if (and term-pending-frame - (eq (window-buffer selected) (current-buffer))) - (progn (term-display-line (car term-pending-frame) - (cdr term-pending-frame)) - (setq term-pending-frame nil) - ;; We have created a new window, so check the window size. - (term-check-size proc))) - - ;; Scroll each window displaying the buffer but (by default) - ;; only if the point matches the process-mark we started with. - (setq win selected) - (while (progn - (setq win (next-window win nil t)) - (if (eq (window-buffer win) (process-buffer proc)) - (let ((scroll term-scroll-to-bottom-on-output)) - (select-window win) - (if (or (= (point) save-marker) - (eq scroll t) (eq scroll 'all) - ;; Maybe user wants point to jump to the end. - (and (eq selected win) - (or (eq scroll 'this) (not save-point))) - (and (eq scroll 'others) - (not (eq selected win)))) - (progn - (goto-char term-home-marker) - (recenter 0) - (goto-char (process-mark proc)) - (if (not (pos-visible-in-window-p (point) win)) - (recenter -1)))) - ;; Optionally scroll so that the text - ;; ends at the bottom of the window. - (if (and term-scroll-show-maximum-output - (>= (point) (process-mark proc))) - (save-excursion - (goto-char (point-max)) - (recenter -1))))) - (not (eq win selected)))) - - (set-marker save-marker nil)) - ;; unwind-protect cleanup-forms follow: - (set-buffer previous-buffer) - (select-window selected)))) - -(defun term-handle-deferred-scroll () - (let ((count (- (term-current-row) term-height))) - (if (>= count 0) - (save-excursion - (goto-char term-home-marker) - (term-vertical-motion (1+ count)) - (set-marker term-home-marker (point)) - (setq term-current-row (1- term-height)))))) - -;;; Handle a character assuming (eq terminal-state 2) - -;;; i.e. we have previously seen Escape followed by ?[. - -(defun term-handle-ansi-escape (proc char) - (cond - ((eq char ?H) ; cursor motion - (if (<= term-terminal-parameter 0) - (setq term-terminal-parameter 1)) - (if (<= term-terminal-previous-parameter 0) - (setq term-terminal-previous-parameter 1)) - (if (> term-terminal-previous-parameter term-height) - (setq term-terminal-previous-parameter term-height)) - (if (> term-terminal-parameter term-width) - (setq term-terminal-parameter term-width)) - (term-goto - (1- term-terminal-previous-parameter) - (1- term-terminal-parameter))) - ;; \E[A - cursor up - ((eq char ?A) - (term-handle-deferred-scroll) - (term-down (- (max 1 term-terminal-parameter)) t)) - ;; \E[B - cursor down - ((eq char ?B) - (term-down (max 1 term-terminal-parameter) t)) - ;; \E[C - cursor right - ((eq char ?C) - (term-move-columns (max 1 term-terminal-parameter))) - ;; \E[D - cursor left - ((eq char ?D) - (term-move-columns (- (max 1 term-terminal-parameter)))) - ;; \E[J - clear to end of screen - ((eq char ?J) - (term-erase-in-display term-terminal-parameter)) - ;; \E[K - clear to end of line - ((eq char ?K) - (term-erase-in-line term-terminal-parameter)) - ;; \E[L - insert lines - ((eq char ?L) - (term-insert-lines (max 1 term-terminal-parameter))) - ;; \E[M - delete lines - ((eq char ?M) - (term-delete-lines (max 1 term-terminal-parameter))) - ;; \E[P - delete chars - ((eq char ?P) - (term-delete-chars (max 1 term-terminal-parameter))) - ;; \E[@ - insert spaces - ((eq char ?@) - (term-insert-spaces (max 1 term-terminal-parameter))) - ;; \E[?h - DEC Private Mode Set - ((eq char ?h) - (cond ((eq term-terminal-parameter 4) - (setq term-insert-mode t)) - ((eq term-terminal-parameter 47) - (term-switch-to-alternate-sub-buffer t)))) - ;; \E[?l - DEC Private Mode Reset - ((eq char ?l) - (cond ((eq term-terminal-parameter 4) - (setq term-insert-mode nil)) - ((eq term-terminal-parameter 47) - (term-switch-to-alternate-sub-buffer nil)))) - ;; \E[m - Set/reset standard mode - ((eq char ?m) - (cond ((eq term-terminal-parameter 7) - (setq term-current-face 'highlight)) - ((eq term-terminal-parameter 4) - (setq term-current-face 'term-underline-face)) - ((eq term-terminal-parameter 1) - (setq term-current-face 'bold)) - (t (setq term-current-face 'default)))) - ;; \E[6n - Report cursor position - ((eq char ?n) - (term-handle-deferred-scroll) - (process-send-string proc - (format "\e[%s;%sR" - (1+ (term-current-row)) - (1+ (term-horizontal-column))))) - ;; \E[r - Set scrolling region - ((eq char ?r) - (term-scroll-region - (1- term-terminal-previous-parameter) - term-terminal-parameter)) - (t))) - -(defun term-scroll-region (top bottom) - "Set scrolling region. -TOP is the top-most line (inclusive) of the new scrolling region, -while BOTTOM is the line following the new scrolling region (e.g. exclusive). -The top-most line is line 0." - (setq term-scroll-start - (if (or (< top 0) (>= top term-height)) - 0 - top)) - (setq term-scroll-end - (if (or (<= bottom term-scroll-start) (> bottom term-height)) - term-height - bottom)) - (setq term-scroll-with-delete - (or (term-using-alternate-sub-buffer) - (not (and (= term-scroll-start 0) - (= term-scroll-end term-height)))))) - -(defun term-switch-to-alternate-sub-buffer (set) - ;; If asked to switch to (from) the alternate sub-buffer, and already (not) - ;; using it, do nothing. This test is needed for some programs (including - ;; emacs) that emit the ti termcap string twice, for unknown reason. - (term-handle-deferred-scroll) - (if (eq set (not (term-using-alternate-sub-buffer))) - (let ((row (term-current-row)) - (col (term-horizontal-column))) - (cond (set - (goto-char (point-max)) - (if (not (eq (preceding-char) ?\n)) - (term-insert-char ?\n 1)) - (setq term-scroll-with-delete t) - (setq term-saved-home-marker (copy-marker term-home-marker)) - (set-marker term-home-marker (point))) - (t - (setq term-scroll-with-delete - (not (and (= term-scroll-start 0) - (= term-scroll-end term-height)))) - (set-marker term-home-marker term-saved-home-marker) - (set-marker term-saved-home-marker nil) - (setq term-saved-home-marker nil) - (goto-char term-home-marker))) - (setq term-current-column nil) - (setq term-current-row 0) - (term-goto row col)))) - -;; Default value for the symbol term-command-hook. - -(defun term-command-hook (string) - (cond ((= (aref string 0) ?\032) - ;; gdb (when invoked with -fullname) prints: - ;; \032\032FULLFILENAME:LINENUMBER:CHARPOS:BEG_OR_MIDDLE:PC\n - (let* ((first-colon (string-match ":" string 1)) - (second-colon - (string-match ":" string (1+ first-colon))) - (filename (substring string 1 first-colon)) - (fileline (string-to-int - (substring string (1+ first-colon) second-colon)))) - (setq term-pending-frame (cons filename fileline)))) - ((= (aref string 0) ?/) - ;; FIXME: If cd fails, should ignore, and not raise error. - (cd (substring string 1))) - ;; Allowing the inferior to call functions in emacs is - ;; probably too big a security hole. - ;; ((= (aref string 0) ?!) - ;; (eval (car (read-from-string string 1)))) - (t)));; Otherwise ignore it - -;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen -;; and that its line LINE is visible. -;; Put the overlay-arrow on the line LINE in that buffer. -;; This is mainly used by gdb. - -(defun term-display-line (true-file line) - (term-display-buffer-line (find-file-noselect true-file) line)) - -(defun term-display-buffer-line (buffer line) - (let* ((window (display-buffer buffer t)) - (pos)) - (save-excursion - (set-buffer buffer) - (save-restriction - (widen) - (goto-line line) - (setq pos (point)) - (setq overlay-arrow-string "=>") - (or overlay-arrow-position - (setq overlay-arrow-position (make-marker))) - (set-marker overlay-arrow-position (point) (current-buffer))) - (cond ((or (< pos (point-min)) (> pos (point-max))) - (widen) - (goto-char pos)))) - (set-window-point window overlay-arrow-position))) - -;;; The buffer-local marker term-home-marker defines the "home position" -;;; (in terms of cursor motion). However, we move the term-home-marker -;;; "down" as needed so that is no more that a window-full above (point-max). - -(defun term-goto-home () - (term-handle-deferred-scroll) - (goto-char term-home-marker) - (setq term-current-row 0) - (setq term-current-column (current-column)) - (setq term-start-line-column term-current-column)) - -(defun term-goto (row col) - (term-handle-deferred-scroll) - (cond ((and term-current-row (>= row term-current-row)) - ;; I assume this is a worthwhile optimization. - (term-vertical-motion 0) - (setq term-current-column term-start-line-column) - (setq row (- row term-current-row))) - (t - (term-goto-home))) - (term-down row) - (term-move-columns col)) - -; The page is full, so enter "pager" mode, and wait for input. - -(defun term-process-pager () - (if (not term-pager-break-map) - (let* ((map (make-keymap)) - (i 0) tmp) -; (while (< i 128) -; (define-key map (make-string 1 i) 'term-send-raw) -; (setq i (1+ i))) - (define-key map "\e" - (lookup-key (current-global-map) "\e")) - (define-key map "\C-x" - (lookup-key (current-global-map) "\C-x")) - (define-key map "\C-u" - (lookup-key (current-global-map) "\C-u")) - (define-key map " " 'term-pager-page) - (define-key map "\r" 'term-pager-line) - (define-key map "?" 'term-pager-help) - (define-key map "h" 'term-pager-help) - (define-key map "b" 'term-pager-back-page) - (define-key map "\177" 'term-pager-back-line) - (define-key map "q" 'term-pager-discard) - (define-key map "D" 'term-pager-disable) - (define-key map "<" 'term-pager-bob) - (define-key map ">" 'term-pager-eob) - - ;; Add menu bar. - (term-if-emacs19 - (term-ifnot-xemacs - (define-key map [menu-bar terminal] term-terminal-menu) - (define-key map [menu-bar signals] term-signals-menu) - (setq tmp (make-sparse-keymap "More pages?")) - (define-key tmp [help] '("Help" . term-pager-help)) - (define-key tmp [disable] - '("Disable paging" . term-fake-pager-disable)) - (define-key tmp [discard] - '("Discard remaining output" . term-pager-discard)) - (define-key tmp [eob] '("Goto to end" . term-pager-eob)) - (define-key tmp [bob] '("Goto to beginning" . term-pager-bob)) - (define-key tmp [line] '("1 line forwards" . term-pager-line)) - (define-key tmp [bline] '("1 line backwards" . term-pager-back-line)) - (define-key tmp [back] '("1 page backwards" . term-pager-back-page)) - (define-key tmp [page] '("1 page forwards" . term-pager-page)) - (define-key map [menu-bar page] (cons "More pages?" tmp)) - )) - - (setq term-pager-break-map map))) -; (let ((process (get-buffer-process (current-buffer)))) -; (stop-process process)) - (setq term-pager-old-local-map (current-local-map)) - (use-local-map term-pager-break-map) - (make-local-variable 'term-old-mode-line-format) - (setq term-old-mode-line-format mode-line-format) - (setq mode-line-format - (list "-- **MORE** " - mode-line-buffer-identification - " [Type ? for help] " - "%-")) - (force-mode-line-update)) - -(defun term-pager-line (lines) - (interactive "p") - (let* ((moved (vertical-motion (1+ lines))) - (deficit (- lines moved))) - (if (> moved lines) - (backward-char)) - (cond ((<= deficit 0) ;; OK, had enough in the buffer for request. - (recenter (1- term-height))) - ((term-pager-continue deficit))))) - -(defun term-pager-page (arg) - "Proceed past the **MORE** break, allowing the next page of output to appear" - (interactive "p") - (term-pager-line (* arg term-height))) - -; Pager mode command to go to beginning of buffer -(defun term-pager-bob () - (interactive) - (goto-char (point-min)) - (if (= (vertical-motion term-height) term-height) - (backward-char)) - (recenter (1- term-height))) - -; pager mode command to go to end of buffer -(defun term-pager-eob () - (interactive) - (goto-char term-home-marker) - (recenter 0) - (goto-char (process-mark (get-buffer-process (current-buffer))))) - -(defun term-pager-back-line (lines) - (interactive "p") - (vertical-motion (- 1 lines)) - (if (not (bobp)) - (backward-char) - (beep) - ;; Move cursor to end of window. - (vertical-motion term-height) - (backward-char)) - (recenter (1- term-height))) - -(defun term-pager-back-page (arg) - (interactive "p") - (term-pager-back-line (* arg term-height))) - -(defun term-pager-discard () - (interactive) - (setq term-terminal-parameter "") - (interrupt-process nil t) - (term-pager-continue term-height)) - -; Disable pager processing. -; Only callable while in pager mode. (Contrast term-disable-pager.) -(defun term-pager-disable () - (interactive) - (if (term-handling-pager) - (term-pager-continue nil) - (setq term-pager-count nil)) - (term-update-mode-line)) - -; Enable pager processing. -(defun term-pager-enable () - (interactive) - (or (term-pager-enabled) - (setq term-pager-count 0)) ;; Or maybe set to (term-current-row) ?? - (term-update-mode-line)) - -(defun term-pager-toggle () - (interactive) - (if (term-pager-enabled) (term-pager-disable) (term-pager-enable))) - -(term-ifnot-xemacs - (defalias 'term-fake-pager-enable 'term-pager-toggle) - (defalias 'term-fake-pager-disable 'term-pager-toggle) - (put 'term-char-mode 'menu-enable '(term-in-line-mode)) - (put 'term-line-mode 'menu-enable '(term-in-char-mode)) - (put 'term-fake-pager-enable 'menu-enable '(not term-pager-count)) - (put 'term-fake-pager-disable 'menu-enable 'term-pager-count)) - -(defun term-pager-help () - "Provide help on commands available in a terminal-emulator **MORE** break" - (interactive) - (message "Terminal-emulator pager break help...") - (sit-for 0) - (with-electric-help - (function (lambda () - (princ (substitute-command-keys -"\\\ -Terminal-emulator MORE break.\n\ -Type one of the following keys:\n\n\ -\\[term-pager-page]\t\tMove forward one page.\n\ -\\[term-pager-line]\t\tMove forward one line.\n\ -\\[universal-argument] N \\[term-pager-page]\tMove N pages forward.\n\ -\\[universal-argument] N \\[term-pager-line]\tMove N lines forward.\n\ -\\[universal-argument] N \\[term-pager-back-line]\tMove N lines back.\n\ -\\[universal-argument] N \\[term-pager-back-page]\t\tMove N pages back.\n\ -\\[term-pager-bob]\t\tMove to the beginning of the buffer.\n\ -\\[term-pager-eob]\t\tMove to the end of the buffer.\n\ -\\[term-pager-discard]\t\tKill pending output and kill process.\n\ -\\[term-pager-disable]\t\tDisable PAGER handling.\n\n\ -\\{term-pager-break-map}\n\ -Any other key is passed through to the program -running under the terminal emulator and disables pager processing until -all pending output has been dealt with.")) - nil)))) - -(defun term-pager-continue (new-count) - (let ((process (get-buffer-process (current-buffer)))) - (use-local-map term-pager-old-local-map) - (setq term-pager-old-local-map nil) - (setq mode-line-format term-old-mode-line-format) - (force-mode-line-update) - (setq term-pager-count new-count) - (set-process-filter process term-pager-old-filter) - (funcall term-pager-old-filter process "") - (continue-process process))) - -;; Make sure there are DOWN blank lines below the current one. -;; Return 0 if we're unable (because of PAGER handling), else return DOWN. - -(defun term-handle-scroll (down) - (let ((scroll-needed - (- (+ (term-current-row) down 1) term-scroll-end))) - (if (> scroll-needed 0) - (let ((save-point (copy-marker (point))) (save-top)) - (goto-char term-home-marker) - (cond (term-scroll-with-delete - ;; delete scroll-needed lines at term-scroll-start - (term-vertical-motion term-scroll-start) - (setq save-top (point)) - (term-vertical-motion scroll-needed) - (delete-region save-top (point)) - (goto-char save-point) - (term-vertical-motion down) - (term-adjust-current-row-cache (- scroll-needed)) - (setq term-current-column nil) - (term-insert-char ?\n scroll-needed)) - ((and (numberp term-pager-count) - (< (setq term-pager-count (- term-pager-count down)) - 0)) - (setq down 0) - (term-process-pager)) - (t - (term-adjust-current-row-cache (- scroll-needed)) - (term-vertical-motion scroll-needed) - (set-marker term-home-marker (point)))) - (goto-char save-point) - (set-marker save-point nil)))) - down) - -(defun term-down (down &optional check-for-scroll) - "Move down DOWN screen lines vertically." - (let ((start-column (term-horizontal-column))) - (if (and check-for-scroll (or term-scroll-with-delete term-pager-count)) - (setq down (term-handle-scroll down))) - (term-adjust-current-row-cache down) - (if (/= (point) (point-max)) - (setq down (- down (term-vertical-motion down)))) - ;; Extend buffer with extra blank lines if needed. - (cond ((> down 0) - (term-insert-char ?\n down) - (setq term-current-column 0) - (setq term-start-line-column 0)) - (t - (setq term-current-column nil) - (setq term-start-line-column (current-column)))) - (if start-column - (term-move-columns start-column)))) - -;; Assuming point is at the beginning of a screen line, -;; if the line above point wraps around, add a ?\n to undo the wrapping. -;; FIXME: Probably should be called more than it is. -(defun term-unwrap-line () - (if (not (bolp)) (insert-before-markers ?\n))) - -(defun term-erase-in-line (kind) - (if (> kind 1) ;; erase left of point - (let ((cols (term-horizontal-column)) (saved-point (point))) - (term-vertical-motion 0) - (delete-region (point) saved-point) - (term-insert-char ?\n cols))) - (if (not (eq kind 1)) ;; erase right of point - (let ((saved-point (point)) - (wrapped (and (zerop (term-horizontal-column)) - (not (zerop (term-current-column)))))) - (term-vertical-motion 1) - (delete-region saved-point (point)) - ;; wrapped is true if we're at the beginning of screen line, - ;; but not a buffer line. If we delete the current screen line - ;; that will make the previous line no longer wrap, and (because - ;; of the way emacs display works) point will be at the end of - ;; the previous screen line rather then the beginning of the - ;; current one. To avoid that, we make sure that current line - ;; contain a space, to force the previous line to continue to wrap. - ;; We could do this always, but it seems preferable to not add the - ;; extra space when wrapped is false. - (if wrapped - (insert ? )) - (insert ?\n) - (put-text-property saved-point (point) 'face 'default) - (goto-char saved-point)))) - -(defun term-erase-in-display (kind) - "Erases (that is blanks out) part of the window. -If KIND is 0, erase from (point) to (point-max); -if KIND is 1, erase from home to point; else erase from home to point-max. -Should only be called when point is at the start of a screen line." - (term-handle-deferred-scroll) - (cond ((eq term-terminal-parameter 0) - (delete-region (point) (point-max)) - (term-unwrap-line)) - ((let ((row (term-current-row)) - (col (term-horizontal-column)) - (start-region term-home-marker) - (end-region (if (eq kind 1) (point) (point-max)))) - (delete-region start-region end-region) - (term-unwrap-line) - (if (eq kind 1) - (term-insert-char ?\n row)) - (setq term-current-column nil) - (setq term-current-row nil) - (term-goto row col))))) - -(defun term-delete-chars (count) - (let ((save-point (point))) - (term-vertical-motion 1) - (term-unwrap-line) - (goto-char save-point) - (move-to-column (+ (term-current-column) count) t) - (delete-region save-point (point)))) - -;;; Insert COUNT spaces after point, but do not change any of -;;; following screen lines. Hence we may have to delete characters -;;; at teh end of this screen line to make room. - -(defun term-insert-spaces (count) - (let ((save-point (point)) (save-eol)) - (term-vertical-motion 1) - (if (bolp) - (backward-char)) - (setq save-eol (point)) - (move-to-column (+ (term-start-line-column) (- term-width count)) t) - (if (> save-eol (point)) - (delete-region (point) save-eol)) - (goto-char save-point) - (term-insert-char ? count) - (goto-char save-point))) - -(defun term-delete-lines (lines) - (let ((start (point)) - (save-current-column term-current-column) - (save-start-line-column term-start-line-column) - (save-current-row (term-current-row))) - (term-down lines) - (delete-region start (point)) - (term-down (- term-scroll-end save-current-row lines)) - (term-insert-char ?\n lines) - (setq term-current-column save-current-column) - (setq term-start-line-column save-start-line-column) - (setq term-current-row save-current-row) - (goto-char start))) - -(defun term-insert-lines (lines) - (let ((start (point)) - (start-deleted) - (save-current-column term-current-column) - (save-start-line-column term-start-line-column) - (save-current-row (term-current-row))) - (term-down (- term-scroll-end save-current-row lines)) - (setq start-deleted (point)) - (term-down lines) - (delete-region start-deleted (point)) - (goto-char start) - (setq term-current-column save-current-column) - (setq term-start-line-column save-start-line-column) - (setq term-current-row save-current-row) - (term-insert-char ?\n lines) - (goto-char start))) - -(defun term-set-output-log (name) - "Record raw inferior process output in a buffer." - (interactive (list (if term-log-buffer - nil - (read-buffer "Record output in buffer: " - (format "%s output-log" - (buffer-name (current-buffer))) - nil)))) - (if (or (null name) (equal name "")) - (progn (setq term-log-buffer nil) - (message "Output logging off.")) - (if (get-buffer name) - nil - (save-excursion - (set-buffer (get-buffer-create name)) - (fundamental-mode) - (buffer-disable-undo (current-buffer)) - (erase-buffer))) - (setq term-log-buffer (get-buffer name)) - (message "Recording terminal emulator output into buffer \"%s\"" - (buffer-name term-log-buffer)))) - -(defun term-stop-photo () - "Discontinue raw inferior process logging." - (interactive) - (term-set-output-log nil)) - -(defun term-show-maximum-output () - "Put the end of the buffer at the bottom of the window." - (interactive) - (goto-char (point-max)) - (recenter -1)) - -;;; Do the user's customisation... - -(defvar term-load-hook nil - "This hook is run when term is loaded in. -This is a good place to put keybindings.") - -(run-hooks 'term-load-hook) - - -;;; Filename/command/history completion in a buffer -;;; =========================================================================== -;;; Useful completion functions, courtesy of the Ergo group. - -;;; Six commands: -;;; term-dynamic-complete Complete or expand command, filename, -;;; history at point. -;;; term-dynamic-complete-filename Complete filename at point. -;;; term-dynamic-list-filename-completions List completions in help buffer. -;;; term-replace-by-expanded-filename Expand and complete filename at point; -;;; replace with expanded/completed name. -;;; term-dynamic-simple-complete Complete stub given candidates. - -;;; These are not installed in the term-mode keymap. But they are -;;; available for people who want them. Shell-mode installs them: -;;; (define-key shell-mode-map "\t" 'term-dynamic-complete) -;;; (define-key shell-mode-map "\M-?" -;;; 'term-dynamic-list-filename-completions))) -;;; -;;; Commands like this are fine things to put in load hooks if you -;;; want them present in specific modes. - -(defvar term-completion-autolist nil - "*If non-nil, automatically list possibilities on partial completion. -This mirrors the optional behavior of tcsh.") - -(defvar term-completion-addsuffix t - "*If non-nil, add a `/' to completed directories, ` ' to file names. -If a cons pair, it should be of the form (DIRSUFFIX . FILESUFFIX) where -DIRSUFFIX and FILESUFFIX are strings added on unambiguous or exact -completion. This mirrors the optional behavior of tcsh.") - -(defvar term-completion-recexact nil - "*If non-nil, use shortest completion if characters cannot be added. -This mirrors the optional behavior of tcsh. - -A non-nil value is useful if `term-completion-autolist' is non-nil too.") - -(defvar term-completion-fignore nil - "*List of suffixes to be disregarded during file completion. -This mirrors the optional behavior of bash and tcsh. - -Note that this applies to `term-dynamic-complete-filename' only.") - -(defvar term-file-name-prefix "" - "Prefix prepended to absolute file names taken from process input. -This is used by term's and shell's completion functions, and by shell's -directory tracking functions.") - - -(defun term-directory (directory) - ;; Return expanded DIRECTORY, with `term-file-name-prefix' if absolute. - (expand-file-name (if (file-name-absolute-p directory) - (concat term-file-name-prefix directory) - directory))) - - -(defun term-word (word-chars) - "Return the word of WORD-CHARS at point, or nil if non is found. -Word constituents are considered to be those in WORD-CHARS, which is like the -inside of a \"[...]\" (see `skip-chars-forward')." - (save-excursion - (let ((limit (point)) - (word (concat "[" word-chars "]")) - (non-word (concat "[^" word-chars "]"))) - (if (re-search-backward non-word nil 'move) - (forward-char 1)) - ;; Anchor the search forwards. - (if (or (eolp) (looking-at non-word)) - nil - (re-search-forward (concat word "+") limit) - (buffer-substring (match-beginning 0) (match-end 0)))))) - - -(defun term-match-partial-filename () - "Return the filename at point, or nil if non is found. -Environment variables are substituted. See `term-word'." - (let ((filename (term-word "~/A-Za-z0-9+@:_.$#,={}-"))) - (and filename (substitute-in-file-name filename)))) - - -(defun term-dynamic-complete () - "Dynamically perform completion at point. -Calls the functions in `term-dynamic-complete-functions' to perform -completion until a function returns non-nil, at which point completion is -assumed to have occurred." - (interactive) - (let ((functions term-dynamic-complete-functions)) - (while (and functions (null (funcall (car functions)))) - (setq functions (cdr functions))))) - - -(defun term-dynamic-complete-filename () - "Dynamically complete the filename at point. -Completes if after a filename. See `term-match-partial-filename' and -`term-dynamic-complete-as-filename'. -This function is similar to `term-replace-by-expanded-filename', except that -it won't change parts of the filename already entered in the buffer; it just -adds completion characters to the end of the filename. A completions listing -may be shown in a help buffer if completion is ambiguous. - -Completion is dependent on the value of `term-completion-addsuffix', -`term-completion-recexact' and `term-completion-fignore', and the timing of -completions listing is dependent on the value of `term-completion-autolist'. - -Returns t if successful." - (interactive) - (if (term-match-partial-filename) - (prog2 (or (eq (selected-window) (minibuffer-window)) - (message "Completing file name...")) - (term-dynamic-complete-as-filename)))) - -(defun term-dynamic-complete-as-filename () - "Dynamically complete at point as a filename. -See `term-dynamic-complete-filename'. Returns t if successful." - (let* ((completion-ignore-case nil) - (completion-ignored-extensions term-completion-fignore) - (success t) - (dirsuffix (cond ((not term-completion-addsuffix) "") - ((not (consp term-completion-addsuffix)) "/") - (t (car term-completion-addsuffix)))) - (filesuffix (cond ((not term-completion-addsuffix) "") - ((not (consp term-completion-addsuffix)) " ") - (t (cdr term-completion-addsuffix)))) - (filename (or (term-match-partial-filename) "")) - (pathdir (file-name-directory filename)) - (pathnondir (file-name-nondirectory filename)) - (directory (if pathdir (term-directory pathdir) default-directory)) - (completion (file-name-completion pathnondir directory)) - (mini-flag (eq (selected-window) (minibuffer-window)))) - (cond ((null completion) - (message "No completions of %s" filename) - (setq success nil)) - ((eq completion t) ; Means already completed "file". - (if term-completion-addsuffix (insert " ")) - (or mini-flag (message "Sole completion"))) - ((string-equal completion "") ; Means completion on "directory/". - (term-dynamic-list-filename-completions)) - (t ; Completion string returned. - (let ((file (concat (file-name-as-directory directory) completion))) - (insert (substring (directory-file-name completion) - (length pathnondir))) - (cond ((symbolp (file-name-completion completion directory)) - ;; We inserted a unique completion. - (insert (if (file-directory-p file) dirsuffix filesuffix)) - (or mini-flag (message "Completed"))) - ((and term-completion-recexact term-completion-addsuffix - (string-equal pathnondir completion) - (file-exists-p file)) - ;; It's not unique, but user wants shortest match. - (insert (if (file-directory-p file) dirsuffix filesuffix)) - (or mini-flag (message "Completed shortest"))) - ((or term-completion-autolist - (string-equal pathnondir completion)) - ;; It's not unique, list possible completions. - (term-dynamic-list-filename-completions)) - (t - (or mini-flag (message "Partially completed"))))))) - success)) - - -(defun term-replace-by-expanded-filename () - "Dynamically expand and complete the filename at point. -Replace the filename with an expanded, canonicalised and completed replacement. -\"Expanded\" means environment variables (e.g., $HOME) and `~'s are replaced -with the corresponding directories. \"Canonicalised\" means `..' and `.' are -removed, and the filename is made absolute instead of relative. For expansion -see `expand-file-name' and `substitute-in-file-name'. For completion see -`term-dynamic-complete-filename'." - (interactive) - (replace-match (expand-file-name (term-match-partial-filename)) t t) - (term-dynamic-complete-filename)) - - -(defun term-dynamic-simple-complete (stub candidates) - "Dynamically complete STUB from CANDIDATES list. -This function inserts completion characters at point by completing STUB from -the strings in CANDIDATES. A completions listing may be shown in a help buffer -if completion is ambiguous. - -Returns nil if no completion was inserted. -Returns `sole' if completed with the only completion match. -Returns `shortest' if completed with the shortest of the completion matches. -Returns `partial' if completed as far as possible with the completion matches. -Returns `listed' if a completion listing was shown. - -See also `term-dynamic-complete-filename'." - (let* ((completion-ignore-case nil) - (candidates (mapcar (function (lambda (x) (list x))) candidates)) - (completions (all-completions stub candidates))) - (cond ((null completions) - (message "No completions of %s" stub) - nil) - ((= 1 (length completions)) ; Gotcha! - (let ((completion (car completions))) - (if (string-equal completion stub) - (message "Sole completion") - (insert (substring completion (length stub))) - (message "Completed")) - (if term-completion-addsuffix (insert " ")) - 'sole)) - (t ; There's no unique completion. - (let ((completion (try-completion stub candidates))) - ;; Insert the longest substring. - (insert (substring completion (length stub))) - (cond ((and term-completion-recexact term-completion-addsuffix - (string-equal stub completion) - (member completion completions)) - ;; It's not unique, but user wants shortest match. - (insert " ") - (message "Completed shortest") - 'shortest) - ((or term-completion-autolist - (string-equal stub completion)) - ;; It's not unique, list possible completions. - (term-dynamic-list-completions completions) - 'listed) - (t - (message "Partially completed") - 'partial))))))) - - -(defun term-dynamic-list-filename-completions () - "List in help buffer possible completions of the filename at point." - (interactive) - (let* ((completion-ignore-case nil) - (filename (or (term-match-partial-filename) "")) - (pathdir (file-name-directory filename)) - (pathnondir (file-name-nondirectory filename)) - (directory (if pathdir (term-directory pathdir) default-directory)) - (completions (file-name-all-completions pathnondir directory))) - (if completions - (term-dynamic-list-completions completions) - (message "No completions of %s" filename)))) - - -(defun term-dynamic-list-completions (completions) - "List in help buffer sorted COMPLETIONS. -Typing SPC flushes the help buffer." - (let ((conf (current-window-configuration))) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list (sort completions 'string-lessp))) - (message "Hit space to flush") - (let (key first) - (if (save-excursion - (set-buffer (get-buffer "*Completions*")) - (setq key (read-key-sequence nil) - first (aref key 0)) - (and (consp first) - (eq (window-buffer (posn-window (event-start first))) - (get-buffer "*Completions*")) - (eq (key-binding key) 'mouse-choose-completion))) - ;; If the user does mouse-choose-completion with the mouse, - ;; execute the command, then delete the completion window. - (progn - (mouse-choose-completion first) - (set-window-configuration conf)) - (if (eq first ?\ ) - (set-window-configuration conf) - (term-ifnot-xemacs - (setq unread-command-events (listify-key-sequence key))) - (term-if-xemacs - (setq unread-command-events (append key nil)))))))) - -;;; Converting process modes to use term mode -;;; =========================================================================== -;;; Renaming variables -;;; Most of the work is renaming variables and functions. These are the common -;;; ones: -;;; Local variables: -;;; last-input-start term-last-input-start -;;; last-input-end term-last-input-end -;;; shell-prompt-pattern term-prompt-regexp -;;; shell-set-directory-error-hook -;;; Miscellaneous: -;;; shell-set-directory -;;; shell-mode-map term-mode-map -;;; Commands: -;;; shell-send-input term-send-input -;;; shell-send-eof term-delchar-or-maybe-eof -;;; kill-shell-input term-kill-input -;;; interrupt-shell-subjob term-interrupt-subjob -;;; stop-shell-subjob term-stop-subjob -;;; quit-shell-subjob term-quit-subjob -;;; kill-shell-subjob term-kill-subjob -;;; kill-output-from-shell term-kill-output -;;; show-output-from-shell term-show-output -;;; copy-last-shell-input Use term-previous-input/term-next-input -;;; -;;; SHELL-SET-DIRECTORY is gone, its functionality taken over by -;;; SHELL-DIRECTORY-TRACKER, the shell mode's term-input-filter-functions. -;;; Term mode does not provide functionality equivalent to -;;; shell-set-directory-error-hook; it is gone. -;;; -;;; term-last-input-start is provided for modes which want to munge -;;; the buffer after input is sent, perhaps because the inferior -;;; insists on echoing the input. The LAST-INPUT-START variable in -;;; the old shell package was used to implement a history mechanism, -;;; but you should think twice before using term-last-input-start -;;; for this; the input history ring often does the job better. -;;; -;;; If you are implementing some process-in-a-buffer mode, called foo-mode, do -;;; *not* create the term-mode local variables in your foo-mode function. -;;; This is not modular. Instead, call term-mode, and let *it* create the -;;; necessary term-specific local variables. Then create the -;;; foo-mode-specific local variables in foo-mode. Set the buffer's keymap to -;;; be foo-mode-map, and its mode to be foo-mode. Set the term-mode hooks -;;; (term-{prompt-regexp, input-filter, input-filter-functions, -;;; get-old-input) that need to be different from the defaults. Call -;;; foo-mode-hook, and you're done. Don't run the term-mode hook yourself; -;;; term-mode will take care of it. The following example, from shell.el, -;;; is typical: -;;; -;;; (defvar shell-mode-map '()) -;;; (cond ((not shell-mode-map) -;;; (setq shell-mode-map (copy-keymap term-mode-map)) -;;; (define-key shell-mode-map "\C-c\C-f" 'shell-forward-command) -;;; (define-key shell-mode-map "\C-c\C-b" 'shell-backward-command) -;;; (define-key shell-mode-map "\t" 'term-dynamic-complete) -;;; (define-key shell-mode-map "\M-?" -;;; 'term-dynamic-list-filename-completions))) -;;; -;;; (defun shell-mode () -;;; (interactive) -;;; (term-mode) -;;; (setq term-prompt-regexp shell-prompt-pattern) -;;; (setq major-mode 'shell-mode) -;;; (setq mode-name "Shell") -;;; (use-local-map shell-mode-map) -;;; (make-local-variable 'shell-directory-stack) -;;; (setq shell-directory-stack nil) -;;; (add-hook 'term-input-filter-functions 'shell-directory-tracker) -;;; (run-hooks 'shell-mode-hook)) -;;; -;;; -;;; Note that make-term is different from make-shell in that it -;;; doesn't have a default program argument. If you give make-shell -;;; a program name of NIL, it cleverly chooses one of explicit-shell-name, -;;; $ESHELL, $SHELL, or /bin/sh. If you give make-term a program argument -;;; of NIL, it barfs. Adjust your code accordingly... -;;; -;;; Completion for term-mode users -;;; -;;; For modes that use term-mode, term-dynamic-complete-functions is the -;;; hook to add completion functions to. Functions on this list should return -;;; non-nil if completion occurs (i.e., further completion should not occur). -;;; You could use term-dynamic-simple-complete to do the bulk of the -;;; completion job. - -(provide 'term) - -;;; term.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/tgud.el --- a/lisp/eterm/tgud.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1264 +0,0 @@ -;; Things to look at: -; (gud-call "") in gud-send-input -; (defvar gud-last-last-frame nil) -; term-prompt-regexp - -;;; tgud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, or xdb -;;; under Emacs - -;; Author: Eric S. Raymond -;; Maintainer: FSF -;; Version: 1.3 -;; Keywords: unix, tools - -;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. - -;; 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 2, 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; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; The ancestral gdb.el was by W. Schelter -;; It was later rewritten by rms. Some ideas were due to Masanobu. -;; Grand Unification (sdb/dbx support) by Eric S. Raymond -;; The overloading code was then rewritten by Barry Warsaw , -;; who also hacked the mode to use comint.el. Shane Hartman -;; added support for xdb (HPUX debugger). Rick Sladkey -;; wrote the GDB command completion code. Dave Love -;; added the IRIX kluge and re-implemented the Mips-ish variant. -;; Then hacked by Per Bothner to use term.el. - -;;; Code: - -(require 'term) -(require 'etags) - -;; ====================================================================== -;; TGUD commands must be visible in C buffers visited by TGUD - -(defvar tgud-key-prefix "\C-x\C-a" - "Prefix of all TGUD commands valid in C buffers.") - -(global-set-key (concat tgud-key-prefix "\C-l") 'tgud-refresh) -(define-key ctl-x-map " " 'tgud-break) ;; backward compatibility hack - -;; ====================================================================== -;; the overloading mechanism - -(defun tgud-overload-functions (tgud-overload-alist) - "Overload functions defined in TGUD-OVERLOAD-ALIST. -This association list has elements of the form - (ORIGINAL-FUNCTION-NAME OVERLOAD-FUNCTION)" - (mapcar - (function (lambda (p) (fset (car p) (symbol-function (cdr p))))) - tgud-overload-alist)) - -(defun tgud-massage-args (file args) - (error "TGUD not properly entered")) - -(defun tgud-marker-filter (str) - (error "TGUD not properly entered")) - -(defun tgud-find-file (f) - (error "TGUD not properly entered")) - -;; ====================================================================== -;; command definition - -;; This macro is used below to define some basic debugger interface commands. -;; Of course you may use `tgud-def' with any other debugger command, including -;; user defined ones. - -;; A macro call like (tgud-def FUNC NAME KEY DOC) expands to a form -;; which defines FUNC to send the command NAME to the debugger, gives -;; it the docstring DOC, and binds that function to KEY in the TGUD -;; major mode. The function is also bound in the global keymap with the -;; TGUD prefix. - -(defmacro tgud-def (func cmd key &optional doc) - "Define FUNC to be a command sending STR and bound to KEY, with -optional doc string DOC. Certain %-escapes in the string arguments -are interpreted specially if present. These are: - - %f name (without directory) of current source file. - %d directory of current source file. - %l number of current source line - %e text of the C lvalue or function-call expression surrounding point. - %a text of the hexadecimal address surrounding point - %p prefix argument to the command (if any) as a number - - The `current' source file is the file of the current buffer (if -we're in a C file) or the source file current at the last break or -step (if we're in the TGUD buffer). - The `current' line is that of the current buffer (if we're in a -source file) or the source line number at the last break or step (if -we're in the TGUD buffer)." - (list 'progn - (list 'defun func '(arg) - (or doc "") - '(interactive "p") - (list 'tgud-call cmd 'arg)) - (if key - (list 'define-key - '(current-local-map) - (concat "\C-c" key) - (list 'quote func))) - (if key - (list 'global-set-key - (list 'concat 'tgud-key-prefix key) - (list 'quote func))))) - -;; Used by tgud-refresh, which should cause tgud-display-frame to redisplay -;; the last frame, even if it's been called before and term-pending-frame has -;; been set to nil. -(defvar tgud-last-last-frame nil) - -;; All debugger-specific information is collected here. -;; Here's how it works, in case you ever need to add a debugger to the mode. -;; -;; Each entry must define the following at startup: -;; -;; -;; term-prompt-regexp -;; tgud--massage-args -;; tgud--marker-filter -;; tgud--find-file -;; -;; The job of the massage-args method is to modify the given list of -;; debugger arguments before running the debugger. -;; -;; The job of the marker-filter method is to detect file/line markers in -;; strings and set the global term-pending-frame to indicate what display -;; action (if any) should be triggered by the marker. Note that only -;; whatever the method *returns* is displayed in the buffer; thus, you -;; can filter the debugger's output, interpreting some and passing on -;; the rest. -;; -;; The job of the find-file method is to visit and return the buffer indicated -;; by the car of tgud-tag-frame. This may be a file name, a tag name, or -;; something else. - -;; ====================================================================== -;; gdb functions - -;;; History of argument lists passed to gdb. -(defvar tgud-gdb-history nil) - -(defun tgud-gdb-massage-args (file args) - (cons "-fullname" (cons file args))) - -;; Don't need to do anything, since term-mode does it for us. -;; (This is so that you can run 'gdb -fullname' from a shell buffer.) -(defun tgud-gdb-marker-filter (string) - string) - -(defun tgud-gdb-find-file (f) - (find-file-noselect f)) - -(defvar gdb-minibuffer-local-map nil - "Keymap for minibuffer prompting of gdb startup command.") -(if gdb-minibuffer-local-map - () - (setq gdb-minibuffer-local-map (copy-keymap minibuffer-local-map)) - (define-key - gdb-minibuffer-local-map "\C-i" 'term-dynamic-complete-filename)) - -;;;###autoload -(defun tgdb (command-line) - "Run gdb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run gdb (like this): " - (if (consp tgud-gdb-history) - (car tgud-gdb-history) - "gdb ") - gdb-minibuffer-local-map nil - '(tgud-gdb-history . 1)))) - (tgud-overload-functions '((tgud-massage-args . tgud-gdb-massage-args) - (tgud-marker-filter . tgud-gdb-marker-filter) - (tgud-find-file . tgud-gdb-find-file) - )) - - (tgud-common-init command-line) - - (tgud-def tgud-break "break %f:%l" "\C-b" "Set breakpoint at current line.") - (tgud-def tgud-tbreak "tbreak %f:%l" "\C-t" "Set breakpoint at current line.") - (tgud-def tgud-remove "clear %l" "\C-d" "Remove breakpoint at current line") - (tgud-def tgud-step "step %p" "\C-s" "Step one source line with display.") - (tgud-def tgud-stepi "stepi %p" "\C-i" "Step one instruction with display.") - (tgud-def tgud-next "next %p" "\C-n" "Step one line (skip functions).") - (tgud-def tgud-cont "cont" "\C-r" "Continue with display.") - (tgud-def tgud-finish "finish" "\C-f" "Finish executing current function.") - (tgud-def tgud-up "up %p" "<" "Up N stack frames (numeric arg).") - (tgud-def tgud-down "down %p" ">" "Down N stack frames (numeric arg).") - (tgud-def tgud-print "print %e" "\C-p" "Evaluate C expression at point.") - - (local-set-key "\C-i" 'tgud-gdb-complete-command) - (setq term-prompt-regexp "^(.*gdb[+]?) *") - (setq paragraph-start term-prompt-regexp) - (run-hooks 'gdb-mode-hook) - ) - -;; One of the nice features of GDB is its impressive support for -;; context-sensitive command completion. We preserve that feature -;; in the TGUD buffer by using a GDB command designed just for Emacs. - -;; The completion process filter indicates when it is finished. -(defvar tgud-gdb-complete-in-progress) - -;; Since output may arrive in fragments we accumulate partials strings here. -(defvar tgud-gdb-complete-string) - -;; We need to know how much of the completion to chop off. -(defvar tgud-gdb-complete-break) - -;; The completion list is constructed by the process filter. -(defvar tgud-gdb-complete-list) - -(defvar tgud-term-buffer nil) - -(defun tgud-gdb-complete-command () - "Perform completion on the GDB command preceding point. -This is implemented using the GDB `complete' command which isn't -available with older versions of GDB." - (interactive) - (let* ((end (point)) - (command (save-excursion - (beginning-of-line) - (and (looking-at term-prompt-regexp) - (goto-char (match-end 0))) - (buffer-substring (point) end))) - command-word) - ;; Find the word break. This match will always succeed. - (string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command) - (setq tgud-gdb-complete-break (match-beginning 2) - command-word (substring command tgud-gdb-complete-break)) - (unwind-protect - (progn - ;; Temporarily install our filter function. - (tgud-overload-functions - '((tgud-marker-filter . tgud-gdb-complete-filter))) - ;; Issue the command to GDB. - (tgud-basic-call (concat "complete " command)) - (setq tgud-gdb-complete-in-progress t - tgud-gdb-complete-string nil - tgud-gdb-complete-list nil) - ;; Slurp the output. - (while tgud-gdb-complete-in-progress - (accept-process-output (get-buffer-process tgud-term-buffer)))) - ;; Restore the old filter function. - (tgud-overload-functions '((tgud-marker-filter . tgud-gdb-marker-filter)))) - ;; Protect against old versions of GDB. - (and tgud-gdb-complete-list - (string-match "^Undefined command: \"complete\"" - (car tgud-gdb-complete-list)) - (error "This version of GDB doesn't support the `complete' command.")) - ;; Sort the list like readline. - (setq tgud-gdb-complete-list - (sort tgud-gdb-complete-list (function string-lessp))) - ;; Remove duplicates. - (let ((first tgud-gdb-complete-list) - (second (cdr tgud-gdb-complete-list))) - (while second - (if (string-equal (car first) (car second)) - (setcdr first (setq second (cdr second))) - (setq first second - second (cdr second))))) - ;; Let term handle the rest. - (term-dynamic-simple-complete command-word tgud-gdb-complete-list))) - -;; The completion process filter is installed temporarily to slurp the -;; output of GDB up to the next prompt and build the completion list. -(defun tgud-gdb-complete-filter (string) - (setq string (concat tgud-gdb-complete-string string)) - (while (string-match "\r?\n" string) - (setq tgud-gdb-complete-list - (cons (substring string tgud-gdb-complete-break (match-beginning 0)) - tgud-gdb-complete-list)) - (setq string (substring string (match-end 0)))) - (if (string-match term-prompt-regexp string) - (progn - (setq tgud-gdb-complete-in-progress nil) - string) - (progn - (setq tgud-gdb-complete-string string) - ""))) - - -;; ====================================================================== -;; sdb functions - -;;; History of argument lists passed to sdb. -(defvar tgud-sdb-history nil) - -(defvar tgud-sdb-needs-tags (not (file-exists-p "/var")) - "If nil, we're on a System V Release 4 and don't need the tags hack.") - -(defvar tgud-sdb-lastfile nil) - -(defun tgud-sdb-massage-args (file args) - (cons file args)) - -(defun tgud-sdb-marker-filter (string) - (cond - ;; System V Release 3.2 uses this format - ((string-match "\\(^0x\\w* in \\|^\\|\n\\)\\([^:\n]*\\):\\([0-9]*\\):.*\n" - string) - (setq term-pending-frame - (cons - (substring string (match-beginning 2) (match-end 2)) - (string-to-int - (substring string (match-beginning 3) (match-end 3)))))) - ;; System V Release 4.0 - ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n" - string) - (setq tgud-sdb-lastfile - (substring string (match-beginning 2) (match-end 2)))) - ((and tgud-sdb-lastfile (string-match "^\\([0-9]+\\):" string)) - (setq term-pending-frame - (cons - tgud-sdb-lastfile - (string-to-int - (substring string (match-beginning 1) (match-end 1)))))) - (t - (setq tgud-sdb-lastfile nil))) - string) - -(defun tgud-sdb-find-file (f) - (if tgud-sdb-needs-tags - (find-tag-noselect f) - (find-file-noselect f))) - -;;;###autoload -(defun tsdb (command-line) - "Run sdb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run sdb (like this): " - (if (consp tgud-sdb-history) - (car tgud-sdb-history) - "sdb ") - nil nil - '(tgud-sdb-history . 1)))) - (if (and tgud-sdb-needs-tags - (not (and (boundp 'tags-file-name) - (stringp tags-file-name) - (file-exists-p tags-file-name)))) - (error "The sdb support requires a valid tags table to work.")) - (tgud-overload-functions '((tgud-massage-args . tgud-sdb-massage-args) - (tgud-marker-filter . tgud-sdb-marker-filter) - (tgud-find-file . tgud-sdb-find-file) - )) - - (tgud-common-init command-line) - - (tgud-def tgud-break "%l b" "\C-b" "Set breakpoint at current line.") - (tgud-def tgud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.") - (tgud-def tgud-remove "%l d" "\C-d" "Remove breakpoint at current line") - (tgud-def tgud-step "s %p" "\C-s" "Step one source line with display.") - (tgud-def tgud-stepi "i %p" "\C-i" "Step one instruction with display.") - (tgud-def tgud-next "S %p" "\C-n" "Step one line (skip functions).") - (tgud-def tgud-cont "c" "\C-r" "Continue with display.") - (tgud-def tgud-print "%e/" "\C-p" "Evaluate C expression at point.") - - (setq term-prompt-regexp "\\(^\\|\n\\)\\*") - (setq paragraph-start term-prompt-regexp) - (run-hooks 'sdb-mode-hook) - ) - -;; ====================================================================== -;; dbx functions - -;;; History of argument lists passed to dbx. -(defvar tgud-dbx-history nil) - -(defun tgud-dbx-massage-args (file args) - (cons file args)) - -(defun tgud-dbx-marker-filter (string) - (if (or (string-match - "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\"" - string) - (string-match - "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\"" - string)) - (setq term-pending-frame - (cons - (substring string (match-beginning 2) (match-end 2)) - (string-to-int - (substring string (match-beginning 1) (match-end 1)))))) - string) - -;; Functions for Mips-style dbx. Given the option `-emacs', documented in -;; OSF1, not necessarily elsewhere, it produces markers similar to gdb's. -(defvar tgud-mips-p - (or (string-match "^mips-[^-]*-ultrix" system-configuration) - ;; We haven't tested tgud on this system: - (string-match "^mips-[^-]*-riscos" system-configuration) - ;; It's documented on OSF/1.3 - (string-match "^mips-[^-]*-osf1" system-configuration) - (string-match "^alpha-[^-]*-osf" system-configuration)) - "Non-nil to assume the MIPS/OSF dbx conventions (argument `-emacs').") - -(defun tgud-mipsdbx-massage-args (file args) - (cons "-emacs" (cons file args))) - -;; This is just like the gdb one except for the regexps since we need to cope -;; with an optional breakpoint number in [] before the ^Z^Z -(defun tgud-mipsdbx-marker-filter (string) - (save-match-data - (setq tgud-marker-acc (concat tgud-marker-acc string)) - (let ((output "")) - - ;; Process all the complete markers in this chunk. - (while (string-match - ;; This is like th gdb marker but with an optional - ;; leading break point number like `[1] ' - "[][ 0-9]*\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" - tgud-marker-acc) - (setq - - ;; Extract the frame position from the marker. - term-pending-frame - (cons (substring tgud-marker-acc (match-beginning 1) (match-end 1)) - (string-to-int (substring tgud-marker-acc - (match-beginning 2) - (match-end 2)))) - - ;; Append any text before the marker to the output we're going - ;; to return - we don't include the marker in this text. - output (concat output - (substring tgud-marker-acc 0 (match-beginning 0))) - - ;; Set the accumulator to the remaining text. - tgud-marker-acc (substring tgud-marker-acc (match-end 0)))) - - ;; Does the remaining text look like it might end with the - ;; beginning of another marker? If it does, then keep it in - ;; tgud-marker-acc until we receive the rest of it. Since we - ;; know the full marker regexp above failed, it's pretty simple to - ;; test for marker starts. - (if (string-match "[][ 0-9]*\032.*\\'" tgud-marker-acc) - (progn - ;; Everything before the potential marker start can be output. - (setq output (concat output (substring tgud-marker-acc - 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq tgud-marker-acc - (substring tgud-marker-acc (match-beginning 0)))) - - (setq output (concat output tgud-marker-acc) - tgud-marker-acc "")) - - output))) - -;; The dbx in IRIX is a pain. It doesn't print the file name when -;; stopping at a breakpoint (but you do get it from the `up' and -;; `down' commands...). The only way to extract the information seems -;; to be with a `file' command, although the current line number is -;; available in $curline. Thus we have to look for output which -;; appears to indicate a breakpoint. Then we prod the dbx sub-process -;; to output the information we want with a combination of the -;; `printf' and `file' commands as a pseudo marker which we can -;; recognise next time through the marker-filter. This would be like -;; the gdb marker but you can't get the file name without a newline... -;; Note that tgud-remove won't work since Irix dbx expects a breakpoint -;; number rather than a line number etc. Maybe this could be made to -;; work by listing all the breakpoints and picking the one(s) with the -;; correct line number, but life's too short. -;; d.love@dl.ac.uk (Dave Love) can be blamed for this - -(defvar tgud-irix-p (string-match "^mips-[^-]*-irix" system-configuration) - "Non-nil to assume the interface appropriate for IRIX dbx. -This works in IRIX 4 and probably IRIX 5.") -;; (It's been tested in IRIX 4 and the output from dbx on IRIX 5 looks -;; the same.) - -;; this filter is influenced by the xdb one rather than the gdb one - -(defun tgud-irixdbx-marker-filter (string) - (save-match-data - (let (result (case-fold-search nil)) - (if (or (string-match term-prompt-regexp string) - (string-match ".*\012" string)) - (setq result (concat tgud-marker-acc string) - tgud-marker-acc "") - (setq tgud-marker-acc (concat tgud-marker-acc string))) - (if result - (cond - ;; look for breakpoint or signal indication e.g.: - ;; [2] Process 1267 (pplot) stopped at [params:338 ,0x400ec0] - ;; Process 1281 (pplot) stopped at [params:339 ,0x400ec8] - ;; Process 1270 (pplot) Floating point exception [._read._read:16 ,0x452188] - ((string-match - "^\\(\\[[0-9]+] \\)?Process +[0-9]+ ([^)]*) [^[]+\\[[^]\n]*]\n" - result) - ;; prod dbx into printing out the line number and file - ;; name in a form we can grok as below - (process-send-string (get-buffer-process tgud-term-buffer) - "printf \"\032\032%1d:\",$curline;file\n")) - ;; look for result of, say, "up" e.g.: - ;; .pplot.pplot(0x800) ["src/pplot.f":261, 0x400c7c] - ;; (this will also catch one of the lines printed by "where") - ((string-match - "^[^ ][^[]*\\[\"\\([^\"]+\\)\":\\([0-9]+\\), [^]]+]\n" - result) - (let ((file (substring result (match-beginning 1) - (match-end 1)))) - (if (file-exists-p file) - (setq term-pending-frame - (cons - (substring - result (match-beginning 1) (match-end 1)) - (string-to-int - (substring - result (match-beginning 2) (match-end 2))))))) - result) - ((string-match ; kluged-up marker as above - "\032\032\\([0-9]*\\):\\(.*\\)\n" result) - (let ((file (substring result (match-beginning 2) (match-end 2)))) - (if (file-exists-p file) - (setq term-pending-frame - (cons - file - (string-to-int - (substring - result (match-beginning 1) (match-end 1))))))) - (setq result (substring result 0 (match-beginning 0)))))) - (or result "")))) - -(defun tgud-dbx-find-file (f) - (find-file-noselect f)) - -;;;###autoload -(defun tdbx (command-line) - "Run dbx on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run dbx (like this): " - (if (consp tgud-dbx-history) - (car tgud-dbx-history) - "dbx ") - nil nil - '(tgud-dbx-history . 1)))) - - (tgud-overload-functions - (cond - (tgud-mips-p - '((tgud-massage-args . tgud-mipsdbx-massage-args) - (tgud-marker-filter . tgud-mipsdbx-marker-filter) - (tgud-find-file . tgud-dbx-find-file))) - (tgud-irix-p - '((tgud-massage-args . tgud-dbx-massage-args) - (tgud-marker-filter . tgud-irixdbx-marker-filter) - (tgud-find-file . tgud-dbx-find-file))) - (t - '((tgud-massage-args . tgud-dbx-massage-args) - (tgud-marker-filter . tgud-dbx-marker-filter) - (tgud-find-file . tgud-dbx-find-file))))) - - (tgud-common-init command-line) - - (cond - (tgud-mips-p - (tgud-def tgud-break "stop at \"%f\":%l" - "\C-b" "Set breakpoint at current line.") - (tgud-def tgud-finish "return" "\C-f" "Finish executing current function.")) - (tgud-irix-p - (tgud-def tgud-break "stop at \"%d%f\":%l" - "\C-b" "Set breakpoint at current line.") - (tgud-def tgud-finish "return" "\C-f" "Finish executing current function.") - ;; Make dbx give out the source location info that we need. - (process-send-string (get-buffer-process tgud-term-buffer) - "printf \"\032\032%1d:\",$curline;file\n")) - (t - (tgud-def tgud-break "file \"%d%f\"\nstop at %l" - "\C-b" "Set breakpoint at current line."))) - - (tgud-def tgud-remove "clear %l" "\C-d" "Remove breakpoint at current line") - (tgud-def tgud-step "step %p" "\C-s" "Step one line with display.") - (tgud-def tgud-stepi "stepi %p" "\C-i" "Step one instruction with display.") - (tgud-def tgud-next "next %p" "\C-n" "Step one line (skip functions).") - (tgud-def tgud-cont "cont" "\C-r" "Continue with display.") - (tgud-def tgud-up "up %p" "<" "Up (numeric arg) stack frames.") - (tgud-def tgud-down "down %p" ">" "Down (numeric arg) stack frames.") - (tgud-def tgud-print "print %e" "\C-p" "Evaluate C expression at point.") - - (setq term-prompt-regexp "^[^)\n]*dbx) *") - (setq paragraph-start term-prompt-regexp) - (run-hooks 'dbx-mode-hook) - ) - -;;---ok -;; ====================================================================== -;; xdb (HP PARISC debugger) functions - -;;; History of argument lists passed to xdb. -(defvar tgud-xdb-history nil) - -(defvar tgud-xdb-directories nil - "*A list of directories that xdb should search for source code. -If nil, only source files in the program directory -will be known to xdb. - -The file names should be absolute, or relative to the directory -containing the executable being debugged.") - -(defun tgud-xdb-massage-args (file args) - (nconc (let ((directories tgud-xdb-directories) - (result nil)) - (while directories - (setq result (cons (car directories) (cons "-d" result))) - (setq directories (cdr directories))) - (nreverse (cons file result))) - args)) - -(defun tgud-xdb-file-name (f) - "Transform a relative pathname to a full pathname in xdb mode" - (let ((result nil)) - (if (file-exists-p f) - (setq result (expand-file-name f)) - (let ((directories tgud-xdb-directories)) - (while directories - (let ((path (concat (car directories) "/" f))) - (if (file-exists-p path) - (setq result (expand-file-name path) - directories nil))) - (setq directories (cdr directories))))) - result)) - -;; xdb does not print the lines all at once, so we have to accumulate them -(defun tgud-xdb-marker-filter (string) - (let (result) - (if (or (string-match term-prompt-regexp string) - (string-match ".*\012" string)) - (setq result (concat tgud-marker-acc string) - tgud-marker-acc "") - (setq tgud-marker-acc (concat tgud-marker-acc string))) - (if result - (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\):" result) - (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):" - result)) - (let ((line (string-to-int - (substring result (match-beginning 2) (match-end 2)))) - (file (tgud-xdb-file-name - (substring result (match-beginning 1) (match-end 1))))) - (if file - (setq term-pending-frame (cons file line)))))) - (or result ""))) - -(defun tgud-xdb-find-file (f) - (let ((realf (tgud-xdb-file-name f))) - (if realf (find-file-noselect realf)))) - -;;;###autoload -(defun txdb (command-line) - "Run xdb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger. - -You can set the variable 'tgud-xdb-directories' to a list of program source -directories if your program contains sources from more than one directory." - (interactive - (list (read-from-minibuffer "Run xdb (like this): " - (if (consp tgud-xdb-history) - (car tgud-xdb-history) - "xdb ") - nil nil - '(tgud-xdb-history . 1)))) - (tgud-overload-functions '((tgud-massage-args . tgud-xdb-massage-args) - (tgud-marker-filter . tgud-xdb-marker-filter) - (tgud-find-file . tgud-xdb-find-file))) - - (tgud-common-init command-line) - - (tgud-def tgud-break "b %f:%l" "\C-b" "Set breakpoint at current line.") - (tgud-def tgud-tbreak "b %f:%l\\t" "\C-t" - "Set temporary breakpoint at current line.") - (tgud-def tgud-remove "db" "\C-d" "Remove breakpoint at current line") - (tgud-def tgud-step "s %p" "\C-s" "Step one line with display.") - (tgud-def tgud-next "S %p" "\C-n" "Step one line (skip functions).") - (tgud-def tgud-cont "c" "\C-r" "Continue with display.") - (tgud-def tgud-up "up %p" "<" "Up (numeric arg) stack frames.") - (tgud-def tgud-down "down %p" ">" "Down (numeric arg) stack frames.") - (tgud-def tgud-finish "bu\\t" "\C-f" "Finish executing current function.") - (tgud-def tgud-print "p %e" "\C-p" "Evaluate C expression at point.") - - (setq term-prompt-regexp "^>") - (setq paragraph-start term-prompt-regexp) - (run-hooks 'xdb-mode-hook)) - -;; ====================================================================== -;; perldb functions - -;;; History of argument lists passed to perldb. -(defvar tgud-perldb-history nil) - -(defun tgud-perldb-massage-args (file args) - (cons "-d" (cons file (cons "-emacs" args)))) - -;; There's no guarantee that Emacs will hand the filter the entire -;; marker at once; it could be broken up across several strings. We -;; might even receive a big chunk with several markers in it. If we -;; receive a chunk of text which looks like it might contain the -;; beginning of a marker, we save it here between calls to the -;; filter. -(defvar tgud-perldb-marker-acc "") - -(defun tgud-perldb-marker-filter (string) - (save-match-data - (setq tgud-marker-acc (concat tgud-marker-acc string)) - (let ((output "")) - - ;; Process all the complete markers in this chunk. - (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n" - tgud-marker-acc) - (setq - - ;; Extract the frame position from the marker. - term-pending-frame - (cons (substring tgud-marker-acc (match-beginning 1) (match-end 1)) - (string-to-int (substring tgud-marker-acc - (match-beginning 2) - (match-end 2)))) - - ;; Append any text before the marker to the output we're going - ;; to return - we don't include the marker in this text. - output (concat output - (substring tgud-marker-acc 0 (match-beginning 0))) - - ;; Set the accumulator to the remaining text. - tgud-marker-acc (substring tgud-marker-acc (match-end 0)))) - - ;; Does the remaining text look like it might end with the - ;; beginning of another marker? If it does, then keep it in - ;; tgud-marker-acc until we receive the rest of it. Since we - ;; know the full marker regexp above failed, it's pretty simple to - ;; test for marker starts. - (if (string-match "\032.*\\'" tgud-marker-acc) - (progn - ;; Everything before the potential marker start can be output. - (setq output (concat output (substring tgud-marker-acc - 0 (match-beginning 0)))) - - ;; Everything after, we save, to combine with later input. - (setq tgud-marker-acc - (substring tgud-marker-acc (match-beginning 0)))) - - (setq output (concat output tgud-marker-acc) - tgud-marker-acc "")) - - output))) - -(defun tgud-perldb-find-file (f) - (find-file-noselect f)) - -;;;###autoload -(defun tperldb (command-line) - "Run perldb on program FILE in buffer *tgud-FILE*. -The directory containing FILE becomes the initial working directory -and source-file directory for your debugger." - (interactive - (list (read-from-minibuffer "Run perldb (like this): " - (if (consp tgud-perldb-history) - (car tgud-perldb-history) - "perl ") - nil nil - '(tgud-perldb-history . 1)))) - (tgud-overload-functions '((tgud-massage-args . tgud-perldb-massage-args) - (tgud-marker-filter . tgud-perldb-marker-filter) - (tgud-find-file . tgud-perldb-find-file) - )) - - (tgud-common-init command-line) - - (tgud-def tgud-break "b %l" "\C-b" "Set breakpoint at current line.") - (tgud-def tgud-remove "d %l" "\C-d" "Remove breakpoint at current line") - (tgud-def tgud-step "s" "\C-s" "Step one source line with display.") - (tgud-def tgud-next "n" "\C-n" "Step one line (skip functions).") - (tgud-def tgud-cont "c" "\C-r" "Continue with display.") -; (tgud-def tgud-finish "finish" "\C-f" "Finish executing current function.") -; (tgud-def tgud-up "up %p" "<" "Up N stack frames (numeric arg).") -; (tgud-def tgud-down "down %p" ">" "Down N stack frames (numeric arg).") - (tgud-def tgud-print "%e" "\C-p" "Evaluate perl expression at point.") - - (setq term-prompt-regexp "^ DB<[0-9]+> ") - (setq paragraph-start term-prompt-regexp) - (run-hooks 'perldb-mode-hook) - ) - -;; -;; End of debugger-specific information -;; - - -;;; When we send a command to the debugger via tgud-call, it's annoying -;;; to see the command and the new prompt inserted into the debugger's -;;; buffer; we have other ways of knowing the command has completed. -;;; -;;; If the buffer looks like this: -;;; -------------------- -;;; (gdb) set args foo bar -;;; (gdb) -!- -;;; -------------------- -;;; (the -!- marks the location of point), and we type `C-x SPC' in a -;;; source file to set a breakpoint, we want the buffer to end up like -;;; this: -;;; -------------------- -;;; (gdb) set args foo bar -;;; Breakpoint 1 at 0x92: file make-docfile.c, line 49. -;;; (gdb) -!- -;;; -------------------- -;;; Essentially, the old prompt is deleted, and the command's output -;;; and the new prompt take its place. -;;; -;;; Not echoing the command is easy enough; you send it directly using -;;; process-send-string, and it never enters the buffer. However, -;;; getting rid of the old prompt is trickier; you don't want to do it -;;; when you send the command, since that will result in an annoying -;;; flicker as the prompt is deleted, redisplay occurs while Emacs -;;; waits for a response from the debugger, and the new prompt is -;;; inserted. Instead, we'll wait until we actually get some output -;;; from the subprocess before we delete the prompt. If the command -;;; produced no output other than a new prompt, that prompt will most -;;; likely be in the first chunk of output received, so we will delete -;;; the prompt and then replace it with an identical one. If the -;;; command produces output, the prompt is moving anyway, so the -;;; flicker won't be annoying. -;;; -;;; So - when we want to delete the prompt upon receipt of the next -;;; chunk of debugger output, we position term-pending-delete-marker at -;;; the start of the prompt; the process filter will notice this, and -;;; delete all text between it and the process output marker. If -;;; term-pending-delete-marker points nowhere, we leave the current -;;; prompt alone. -(defvar term-pending-delete-marker nil) - - -(defun tgud-mode () - "Major mode for interacting with an inferior debugger process. - - You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx, -or M-x xdb. Each entry point finishes by executing a hook; `gdb-mode-hook', -`sdb-mode-hook', `dbx-mode-hook' or `xdb-mode-hook' respectively. - -After startup, the following commands are available in both the TGUD -interaction buffer and any source buffer TGUD visits due to a breakpoint stop -or step operation: - -\\[tgud-break] sets a breakpoint at the current file and line. In the -TGUD buffer, the current file and line are those of the last breakpoint or -step. In a source buffer, they are the buffer's file and current line. - -\\[tgud-remove] removes breakpoints on the current file and line. - -\\[tgud-refresh] displays in the source window the last line referred to -in the tgud buffer. - -\\[tgud-step], \\[tgud-next], and \\[tgud-stepi] do a step-one-line, -step-one-line (not entering function calls), and step-one-instruction -and then update the source window with the current file and position. -\\[tgud-cont] continues execution. - -\\[tgud-print] tries to find the largest C lvalue or function-call expression -around point, and sends it to the debugger for value display. - -The above commands are common to all supported debuggers except xdb which -does not support stepping instructions. - -Under gdb, sdb and xdb, \\[tgud-tbreak] behaves exactly like \\[tgud-break], -except that the breakpoint is temporary; that is, it is removed when -execution stops on it. - -Under gdb, dbx, and xdb, \\[tgud-up] pops up through an enclosing stack -frame. \\[tgud-down] drops back down through one. - -If you are using gdb or xdb, \\[tgud-finish] runs execution to the return from -the current function and stops. - -All the keystrokes above are accessible in the TGUD buffer -with the prefix C-c, and in all buffers through the prefix C-x C-a. - -All pre-defined functions for which the concept make sense repeat -themselves the appropriate number of times if you give a prefix -argument. - -You may use the `tgud-def' macro in the initialization hook to define other -commands. - -Other commands for interacting with the debugger process are inherited from -term mode, which see." - (interactive) - (term-mode) - (setq major-mode 'tgud-mode) - (setq mode-name "Debugger") - (setq mode-line-process '(":%s")) - (use-local-map (copy-keymap term-mode-map)) - (define-key (current-local-map) "\C-m" 'tgud-send-input) - (define-key (current-local-map) "\C-c\C-l" 'tgud-refresh) - (make-local-variable 'term-prompt-regexp) - (make-local-variable 'paragraph-start) - (run-hooks 'tgud-mode-hook) -) - -(defun tgud-send-input () - (interactive) - (let ((proc (get-buffer-process (current-buffer)))) - (if (not proc) (error "Current buffer has no process") - ;; If input line is empty, use tgud-call to get prompt deleted. - (if (and (= (point) (process-mark proc)) (= (point) (point-max))) - (tgud-call "") - (term-send-input))))) - -;; Chop STRING into words separated by SPC or TAB and return a list of them. -(defun tgud-chop-words (string) - (let ((i 0) (beg 0) - (len (length string)) - (words nil)) - (while (< i len) - (if (memq (aref string i) '(?\t ? )) - (progn - (setq words (cons (substring string beg i) words) - beg (1+ i)) - (while (and (< beg len) (memq (aref string beg) '(?\t ? ))) - (setq beg (1+ beg))) - (setq i (1+ beg))) - (setq i (1+ i)))) - (if (< beg len) - (setq words (cons (substring string beg) words))) - (nreverse words))) - -;; Perform initializations common to all debuggers. -(defun tgud-common-init (command-line) - (let* ((words (tgud-chop-words command-line)) - (program (car words)) - (file-word (let ((w (cdr words))) - (while (and w (= ?- (aref (car w) 0))) - (setq w (cdr w))) - (car w))) - (args (delq file-word (cdr words))) - (file (and file-word - (expand-file-name (substitute-in-file-name file-word)))) - (filepart (and file-word (file-name-nondirectory file)))) - (switch-to-buffer (concat "*tgud-" filepart "*")) - (and file-word (setq default-directory (file-name-directory file))) - (or (bolp) (newline)) - (insert "Current directory is " default-directory "\n") - (apply 'make-term (concat "tgud-" filepart) program nil - (if file-word (tgud-massage-args file args)))) - (tgud-mode) - ;; Note the insertion about of the line giving the "Current directory" - ;; is not known about by the terminal emulator, so clear the - ;; current-row cache to avoid confusion. - (setq term-current-row nil) - (set-process-filter (get-buffer-process (current-buffer)) 'tgud-filter) - (set-process-sentinel (get-buffer-process (current-buffer)) 'tgud-sentinel) - (tgud-set-buffer) - ) - -(defun tgud-set-buffer () - (cond ((eq major-mode 'tgud-mode) - (setq tgud-term-buffer (current-buffer))))) - -;; These functions are responsible for inserting output from your debugger -;; into the buffer. The hard work is done by the method that is -;; the value of tgud-marker-filter. - -(defun tgud-filter (proc string) - ;; Here's where the actual buffer insertion is done - (set-buffer (process-buffer proc)) - (let ((inhibit-quit t)) ;; ??? - (term-emulate-terminal proc (tgud-marker-filter string)))) - -(defun tgud-sentinel (proc msg) - (cond ((null (buffer-name (process-buffer proc))) - ;; buffer killed - ;; Stop displaying an arrow in a source file. - (setq overlay-arrow-position nil) - (set-process-buffer proc nil)) - ((memq (process-status proc) '(signal exit)) - ;; Stop displaying an arrow in a source file. - (setq overlay-arrow-position nil) - ;; Fix the mode line. - (setq mode-line-process - (concat ":" - (symbol-name (process-status proc)))) - (let* ((obuf (current-buffer))) - ;; save-excursion isn't the right thing if - ;; process-buffer is current-buffer - (unwind-protect - (progn - ;; Write something in *compilation* and hack its mode line, - (set-buffer (process-buffer proc)) - ;; Force mode line redisplay soon - (set-buffer-modified-p (buffer-modified-p)) - (if (eobp) - (insert ?\n mode-name " " msg) - (save-excursion - (goto-char (point-max)) - (insert ?\n mode-name " " msg))) - ;; If buffer and mode line will show that the process - ;; is dead, we can delete it now. Otherwise it - ;; will stay around until M-x list-processes. - (delete-process proc)) - ;; Restore old buffer, but don't restore old point - ;; if obuf is the tgud buffer. - (set-buffer obuf)))))) - -(defun tgud-display-frame () - "Find and obey the last filename-and-line marker from the debugger. -Obeying it means displaying in another window the specified file and line." - (interactive) - (if term-pending-frame - (progn - (tgud-set-buffer) - (term-display-buffer-line (tgud-visit-file (car term-pending-frame)) - (cdr term-pending-frame)) - (setq term-pending-frame nil)))) - -;;; The tgud-call function must do the right thing whether its invoking -;;; keystroke is from the TGUD buffer itself (via major-mode binding) -;;; or a C buffer. In the former case, we want to supply data from -;;; term-pending-frame. Here's how we do it: - -(defun tgud-format-command (str arg) - (let ((insource (not (eq (current-buffer) tgud-term-buffer))) - (frame (or term-pending-frame tgud-last-last-frame)) - result) - (while (and str (string-match "\\([^%]*\\)%\\([adeflp]\\)" str)) - (let ((key (string-to-char (substring str (match-beginning 2)))) - subst) - (cond - ((eq key ?f) - (setq subst (file-name-nondirectory (if insource - (buffer-file-name) - (car frame))))) - ((eq key ?d) - (setq subst (file-name-directory (if insource - (buffer-file-name) - (car frame))))) - ((eq key ?l) - (setq subst (if insource - (save-excursion - (beginning-of-line) - (save-restriction (widen) - (1+ (count-lines 1 (point))))) - (cdr frame)))) - ((eq key ?e) - (setq subst (find-c-expr))) - ((eq key ?a) - (setq subst (tgud-read-address))) - ((eq key ?p) - (setq subst (if arg (int-to-string arg) "")))) - (setq result (concat result - (substring str (match-beginning 1) (match-end 1)) - subst))) - (setq str (substring str (match-end 2)))) - ;; There might be text left in STR when the loop ends. - (concat result str))) - -(defun tgud-read-address () - "Return a string containing the core-address found in the buffer at point." - (save-excursion - (let ((pt (point)) found begin) - (setq found (if (search-backward "0x" (- pt 7) t) (point))) - (cond - (found (forward-char 2) - (buffer-substring found - (progn (re-search-forward "[^0-9a-f]") - (forward-char -1) - (point)))) - (t (setq begin (progn (re-search-backward "[^0-9]") - (forward-char 1) - (point))) - (forward-char 1) - (re-search-forward "[^0-9]") - (forward-char -1) - (buffer-substring begin (point))))))) - -(defun tgud-call (fmt &optional arg) - (let ((msg (tgud-format-command fmt arg))) - (message "Command: %s" msg) - (sit-for 0) - (tgud-basic-call msg))) - -(defun tgud-basic-call (command) - "Invoke the debugger COMMAND displaying source in other window." - (interactive) - (tgud-set-buffer) - (let ((proc (get-buffer-process tgud-term-buffer))) - - ;; Arrange for the current prompt to get deleted. - (save-excursion - (set-buffer tgud-term-buffer) - (goto-char (process-mark proc)) - (beginning-of-line) - (if (looking-at term-prompt-regexp) - (set-marker term-pending-delete-marker (point))) - (term-send-invisible command proc)))) - -(defun tgud-refresh (&optional arg) - "Fix up a possibly garbled display, and redraw the arrow." - (interactive "P") - (recenter arg) - (or term-pending-frame (setq term-pending-frame tgud-last-last-frame)) - (tgud-display-frame)) - -;;; Code for parsing expressions out of C code. The single entry point is -;;; find-c-expr, which tries to return an lvalue expression from around point. -;;; -;;; The rest of this file is a hacked version of gdbsrc.el by -;;; Debby Ayers , -;;; Rich Schaefer Schlumberger, Austin, Tx. - -(defun find-c-expr () - "Returns the C expr that surrounds point." - (interactive) - (save-excursion - (let ((p) (expr) (test-expr)) - (setq p (point)) - (setq expr (expr-cur)) - (setq test-expr (expr-prev)) - (while (expr-compound test-expr expr) - (setq expr (cons (car test-expr) (cdr expr))) - (goto-char (car expr)) - (setq test-expr (expr-prev))) - (goto-char p) - (setq test-expr (expr-next)) - (while (expr-compound expr test-expr) - (setq expr (cons (car expr) (cdr test-expr))) - (setq test-expr (expr-next)) - ) - (buffer-substring (car expr) (cdr expr))))) - -(defun expr-cur () - "Returns the expr that point is in; point is set to beginning of expr. -The expr is represented as a cons cell, where the car specifies the point in -the current buffer that marks the beginning of the expr and the cdr specifies -the character after the end of the expr." - (let ((p (point)) (begin) (end)) - (expr-backward-sexp) - (setq begin (point)) - (expr-forward-sexp) - (setq end (point)) - (if (>= p end) - (progn - (setq begin p) - (goto-char p) - (expr-forward-sexp) - (setq end (point)) - ) - ) - (goto-char begin) - (cons begin end))) - -(defun expr-backward-sexp () - "Version of `backward-sexp' that catches errors." - (condition-case nil - (backward-sexp) - (error t))) - -(defun expr-forward-sexp () - "Version of `forward-sexp' that catches errors." - (condition-case nil - (forward-sexp) - (error t))) - -(defun expr-prev () - "Returns the previous expr, point is set to beginning of that expr. -The expr is represented as a cons cell, where the car specifies the point in -the current buffer that marks the beginning of the expr and the cdr specifies -the character after the end of the expr" - (let ((begin) (end)) - (expr-backward-sexp) - (setq begin (point)) - (expr-forward-sexp) - (setq end (point)) - (goto-char begin) - (cons begin end))) - -(defun expr-next () - "Returns the following expr, point is set to beginning of that expr. -The expr is represented as a cons cell, where the car specifies the point in -the current buffer that marks the beginning of the expr and the cdr specifies -the character after the end of the expr." - (let ((begin) (end)) - (expr-forward-sexp) - (expr-forward-sexp) - (setq end (point)) - (expr-backward-sexp) - (setq begin (point)) - (cons begin end))) - -(defun expr-compound-sep (span-start span-end) - "Returns '.' for '->' & '.', returns ' ' for white space, -returns '?' for other punctuation." - (let ((result ? ) - (syntax)) - (while (< span-start span-end) - (setq syntax (char-syntax (char-after span-start))) - (cond - ((= syntax ? ) t) - ((= syntax ?.) (setq syntax (char-after span-start)) - (cond - ((= syntax ?.) (setq result ?.)) - ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>)) - (setq result ?.) - (setq span-start (+ span-start 1))) - (t (setq span-start span-end) - (setq result ??))))) - (setq span-start (+ span-start 1))) - result)) - -(defun expr-compound (first second) - "Non-nil if concatenating FIRST and SECOND makes a single C token. -The two exprs are represented as a cons cells, where the car -specifies the point in the current buffer that marks the beginning of the -expr and the cdr specifies the character after the end of the expr. -Link exprs of the form: - Expr -> Expr - Expr . Expr - Expr (Expr) - Expr [Expr] - (Expr) Expr - [Expr] Expr" - (let ((span-start (cdr first)) - (span-end (car second)) - (syntax)) - (setq syntax (expr-compound-sep span-start span-end)) - (cond - ((= (car first) (car second)) nil) - ((= (cdr first) (cdr second)) nil) - ((= syntax ?.) t) - ((= syntax ? ) - (setq span-start (char-after (- span-start 1))) - (setq span-end (char-after span-end)) - (cond - ((= span-start ?) ) t ) - ((= span-start ?] ) t ) - ((= span-end ?( ) t ) - ((= span-end ?[ ) t ) - (t nil)) - ) - (t nil)))) - -(provide 'tgud) - -;;; tgud.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/eterm/tshell.el --- a/lisp/eterm/tshell.el Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,817 +0,0 @@ -;;; tshell.el --- specialized term.el for running the shell. - -;; Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc. - -;; Author: Per Bothner -;; Original comint version author: Olin Shivers -;; Comint version maintainer: Simon Marshall -;; Keywords: processes - -;; 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 2, 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; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;;; Please send me bug reports, bug fixes, and extensions, so that I can -;;; merge them into the master source. -;;; - Olin Shivers (shivers@cs.cmu.edu) -;;; - Simon Marshall (s.marshall@dcs.hull.ac.uk) - -;;; This file defines a a shell-in-a-buffer package (shell mode) built -;;; on top of term mode. This is actually cmushell with things -;;; renamed to replace its counterpart in Emacs 18. cmushell is more -;;; featureful, robust, and uniform than the Emacs 18 version. - -;;; Since this mode is built on top of the general command-interpreter-in- -;;; a-buffer mode (term mode), it shares a common base functionality, -;;; and a common set of bindings, with all modes derived from term mode. -;;; This makes these modes easier to use. - -;;; For documentation on the functionality provided by term mode, and -;;; the hooks available for customising it, see the file term.el. -;;; For further information on shell mode, see the comments below. - -;;; Needs fixin: -;;; When sending text from a source file to a subprocess, the process-mark can -;;; move off the window, so you can lose sight of the process interactions. -;;; Maybe I should ensure the process mark is in the window when I send -;;; text to the process? Switch selectable? - -;; YOUR .EMACS FILE -;;============================================================================= -;; Some suggestions for your .emacs file. -;; -;; ;; Define C-c t to run my favorite command in shell mode: -;; (setq tshell-mode-hook -;; '((lambda () -;; (define-key tshell-mode-map "\C-ct" 'favorite-cmd)))) - - -;;; Brief Command Documentation: -;;;============================================================================ -;;; Term Mode Commands: (common to tshell and all term-derived modes) -;;; -;;; m-p term-previous-input Cycle backwards in input history -;;; m-n term-next-input Cycle forwards -;;; m-r term-previous-matching-input Previous input matching a regexp -;;; m-R term-previous-matching-input-from-input -"- matching input -;;; m-s term-next-matching-input Next input that matches -;;; m-S term-next-matching-input-from-input -"- matching input -;;; m-c-l term-show-output Show last batch of process output -;;; return term-send-input -;;; c-c c-a term-bol Beginning of line; skip prompt -;;; c-d term-delchar-or-maybe-eof Delete char unless at end of buff. -;;; c-c c-u term-kill-input ^u -;;; c-c c-w backward-kill-word ^w -;;; c-c c-c term-interrupt-subjob ^c -;;; c-c c-z term-stop-subjob ^z -;;; c-c c-\ term-quit-subjob ^\ -;;; c-c c-o term-kill-output Delete last batch of process output -;;; c-c c-r term-show-output Show last batch of process output -;;; c-c c-h term-dynamic-list-input-ring List input history -;;; term-send-invisible Read line w/o echo & send to proc -;;; term-continue-subjob Useful if you accidentally suspend -;;; top-level job -;;; term-mode-hook is the term mode hook. - -;;; Tshell Mode Commands: -;;; tshell Fires up the shell process -;;; tab term-dynamic-complete Complete filename/command/history -;;; m-? term-dynamic-list-filename-completions List completions in help buffer -;;; m-c-f tshell-forward-command Forward a shell command -;;; m-c-b tshell-backward-command Backward a shell command -;;; dirs Resync the buffer's dir stack -;;; dirtrack-toggle Turn dir tracking on/off -;;; tshell-strip-ctrl-m Remove trailing ^Ms from output -;;; -;;; The tshell mode hook is tshell-mode-hook -;;; term-prompt-regexp is initialised to tshell-prompt-pattern, for backwards -;;; compatibility. - -;;; Read the rest of this file for more information. - -;;; SHELL.EL COMPATIBILITY -;;; Notes from when this was called cmushell, and was not the standard emacs -;;; shell package. -;;;============================================================================ -;;; In brief: this package should have no trouble coexisting with shell.el. -;;; -;;; Most customising variables -- e.g., explicit-shell-file-name -- are the -;;; same, so the users shouldn't have much trouble. Hooks have different -;;; names, however, so you can customise tshell mode differently from cmushell -;;; mode. You basically just have to remember to type M-x cmushell instead of -;;; M-x shell. -;;; -;;; It would be nice if this file was completely plug-compatible with the old -;;; shell package -- if you could just name this file shell.el, and have it -;;; transparently replace the old one. But you can't. Several other packages -;;; (tex-mode, background, dbx, gdb, kermit, monkey, prolog, telnet) are also -;;; clients of shell mode. These packages assume detailed knowledge of shell -;;; mode internals in ways that are incompatible with cmushell mode (mostly -;;; because of cmushell mode's greater functionality). So, unless we are -;;; willing to port all of these packages, we can't have this file be a -;;; complete replacement for shell.el -- that is, we can't name this file -;;; shell.el, and its main entry point (shell), because dbx.el will break -;;; when it loads it in and tries to use it. -;;; -;;; There are two ways to fix this. One: rewrite these other modes to use the -;;; new package. This is a win, but can't be assumed. The other, backwards -;;; compatible route, is to make this package non-conflict with shell.el, so -;;; both files can be loaded in at the same time. And *that* is why some -;;; functions and variables have different names: (cmushell), -;;; cmushell-mode-map, that sort of thing. All the names have been carefully -;;; chosen so that shell.el and cmushell.el won't tromp on each other. - -;;; Customization and Buffer Variables -;;; =========================================================================== -;;; - -;;; Code: - -(require 'term) - -;;;###autoload -(defvar tshell-prompt-pattern "^[^#$%>\n]*[#$%>] *" - "Regexp to match prompts in the inferior shell. -Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well. -This variable is used to initialise `term-prompt-regexp' in the -shell buffer. - -The pattern should probably not match more than one line. If it does, -tshell-mode may become confused trying to distinguish prompt from input -on lines which don't start with a prompt. - -This is a fine thing to set in your `.emacs' file.") - -(defvar tshell-completion-fignore nil - "*List of suffixes to be disregarded during file/command completion. -This variable is used to initialize `term-completion-fignore' in the shell -buffer. The default is nil, for compatibility with most shells. -Some people like (\"~\" \"#\" \"%\"). - -This is a fine thing to set in your `.emacs' file.") - -(defvar tshell-delimiter-argument-list '(?\| ?& ?< ?> ?\( ?\) ?\;) - "List of characters to recognise as separate arguments. -This variable is used to initialize `term-delimiter-argument-list' in the -shell buffer. The default is (?\\| ?& ?< ?> ?\\( ?\\) ?\\;). - -This is a fine thing to set in your `.emacs' file.") - -(defvar tshell-dynamic-complete-functions - '(term-replace-by-expanded-history - tshell-dynamic-complete-environment-variable - tshell-dynamic-complete-command - tshell-replace-by-expanded-directory - term-dynamic-complete-filename) - "List of functions called to perform completion. -This variable is used to initialise `term-dynamic-complete-functions' in the -shell buffer. - -This is a fine thing to set in your `.emacs' file.") - -(defvar shell-command-regexp "[^;&|\n]+" - "*Regexp to match a single command within a pipeline. -This is used for directory tracking and does not do a perfect job.") - -(defvar shell-completion-execonly t - "*If non-nil, use executable files only for completion candidates. -This mirrors the optional behavior of tcsh. - -Detecting executability of files may slow command completion considerably.") - -(defvar shell-popd-regexp "popd" - "*Regexp to match subshell commands equivalent to popd.") - -(defvar shell-pushd-regexp "pushd" - "*Regexp to match subshell commands equivalent to pushd.") - -(defvar shell-pushd-tohome nil - "*If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd). -This mirrors the optional behavior of tcsh.") - -(defvar shell-pushd-dextract nil - "*If non-nil, make \"pushd +n\" pop the nth dir to the stack top. -This mirrors the optional behavior of tcsh.") - -(defvar shell-pushd-dunique nil - "*If non-nil, make pushd only add unique directories to the stack. -This mirrors the optional behavior of tcsh.") - -(defvar shell-cd-regexp "cd" - "*Regexp to match subshell commands equivalent to cd.") - -;; explicit-shell-file-name nil is in term.el. - -(defvar explicit-csh-args - (if (eq system-type 'hpux) - ;; -T persuades HP's csh not to think it is smarter - ;; than us about what terminal modes to use. - '("-i" "-T") - '("-i")) - "*Args passed to inferior shell by M-x tshell, if the shell is csh. -Value is a list of strings, which may be nil.") - -(defvar tshell-input-autoexpand 'history - "*If non-nil, expand input command history references on completion. -This mirrors the optional behavior of tcsh (its autoexpand and histlit). - -If the value is `input', then the expansion is seen on input. -If the value is `history', then the expansion is only when inserting -into the buffer's input ring. See also `term-magic-space' and -`term-dynamic-complete'. - -This variable supplies a default for `term-input-autoexpand', -for Tshell mode only.") - -(defvar tshell-dirstack nil - "List of directories saved by pushd in this buffer's shell. -Thus, this does not include the shell's current directory.") - -(defvar tshell-dirtrackp t - "Non-nil in a shell buffer means directory tracking is enabled.") - -(defvar tshell-last-dir nil - "Keep track of last directory for ksh `cd -' command.") - -(defvar tshell-dirstack-query nil - "Command used by `tshell-resync-dir' to query the shell.") - -(defvar tshell-mode-map nil) -(cond ((not tshell-mode-map) - (setq tshell-mode-map (copy-keymap term-mode-map)) - (define-key tshell-mode-map "\C-c\C-f" 'tshell-forward-command) - (define-key tshell-mode-map "\C-c\C-b" 'tshell-backward-command) - (define-key tshell-mode-map "\t" 'term-dynamic-complete) - (define-key tshell-mode-map "\M-?" - 'term-dynamic-list-filename-completions) -;;; XEmacs change [JTL]: We don't have define-key-after -;;; (and we don't need it ...) -;;; (define-key-after (lookup-key tshell-mode-map [menu-bar completion]) -;;; [complete-env-variable] '("Complete Env. Variable Name" . -;;; tshell-dynamic-complete-environment-variable) -;;; 'complete-file) -;;; (define-key-after (lookup-key tshell-mode-map [menu-bar completion]) -;;; [expand-directory] '("Expand Directory Reference" . -;;; tshell-replace-by-expanded-directory) -;;; 'complete-expand) - )) - -(defvar tshell-mode-hook '() - "*Hook for customising Tshell mode.") - - -;;; Basic Procedures -;;; =========================================================================== -;;; - -(defun tshell-mode () - "Major mode for interacting with an inferior shell. -Return after the end of the process' output sends the text from the - end of process to the end of the current line. -Return before end of process output copies the current line (except - for the prompt) to the end of the buffer and sends it. -M-x term-send-invisible reads a line of text without echoing it, - and sends it to the shell. This is useful for entering passwords. - -If you accidentally suspend your process, use \\[term-continue-subjob] -to continue it. - -cd, pushd and popd commands given to the shell are watched by Emacs to keep -this buffer's default directory the same as the shell's working directory. -M-x dirs queries the shell and resyncs Emacs' idea of what the current - directory stack is. -M-x dirtrack-toggle turns directory tracking on and off. - -\\{tshell-mode-map} -Customization: Entry to this mode runs the hooks on `term-mode-hook' and -`tshell-mode-hook' (in that order). Before each input, the hooks on -`term-input-filter-functions' are run. - -Variables `shell-cd-regexp', `shell-pushd-regexp' and `shell-popd-regexp' -are used to match their respective commands, while `shell-pushd-tohome', -`shell-pushd-dextract' and `shell-pushd-dunique' control the behavior of the -relevant command. - -Variables `term-completion-autolist', `term-completion-addsuffix', -`term-completion-recexact' and `term-completion-fignore' control the -behavior of file name, command name and variable name completion. Variable -`shell-completion-execonly' controls the behavior of command name completion. -Variable `tshell-completion-fignore' is used to initialise the value of -`term-completion-fignore'. - -Variables `term-input-ring-file-name' and `term-input-autoexpand' control -the initialisation of the input ring history, and history expansion. - -Variables `term-output-filter-functions', a hook, and -`term-scroll-to-bottom-on-input' and `term-scroll-to-bottom-on-output' -control whether input and output cause the window to scroll to the end of the -buffer." - (interactive) - (term-mode) - (setq major-mode 'tshell-mode) - (setq mode-name "Shell") - (use-local-map tshell-mode-map) - (setq term-prompt-regexp tshell-prompt-pattern) - (setq term-completion-fignore tshell-completion-fignore) - (setq term-delimiter-argument-list tshell-delimiter-argument-list) - (setq term-dynamic-complete-functions tshell-dynamic-complete-functions) - (make-local-variable 'paragraph-start) - (setq paragraph-start term-prompt-regexp) - (make-local-variable 'tshell-dirstack) - (setq tshell-dirstack nil) - (setq tshell-last-dir nil) - (make-local-variable 'tshell-dirtrackp) - (setq tshell-dirtrackp t) - (add-hook 'term-input-filter-functions 'tshell-directory-tracker) - (setq term-input-autoexpand tshell-input-autoexpand) - ;; shell-dependent assignments. - (let ((shell (file-name-nondirectory (car - (process-command (get-buffer-process (current-buffer))))))) - (setq term-input-ring-file-name - (or (getenv "HISTFILE") - (cond ((string-equal shell "bash") "~/.bash_history") - ((string-equal shell "ksh") "~/.sh_history") - (t "~/.history")))) - (if (equal term-input-ring-file-name "/dev/null") - (setq term-input-ring-file-name nil)) - (setq tshell-dirstack-query - (if (string-match "^k?sh$" shell) "pwd" "dirs"))) - (run-hooks 'tshell-mode-hook) - (term-read-input-ring t)) - -;;;###autoload -(defun tshell () - "Run an inferior shell, with I/O through buffer *shell*. -If buffer exists but shell process is not running, make new shell. -If buffer exists and shell process is running, just switch to buffer `*shell*'. -Program used comes from variable `explicit-shell-file-name', - or (if that is nil) from the ESHELL environment variable, - or else from SHELL if there is no ESHELL. -If a file `~/.emacs_SHELLNAME' exists, it is given as initial input - (Note that this may lose due to a timing error if the shell - discards input when it starts up.) -The buffer is put in Tshell mode, giving commands for sending input -and controlling the subjobs of the shell. See `tshell-mode'. -See also the variable `tshell-prompt-pattern'. - -The shell file name (sans directories) is used to make a symbol name -such as `explicit-csh-args'. If that symbol is a variable, -its value is used as a list of arguments when invoking the shell. -Otherwise, one argument `-i' is passed to the shell. - -\(Type \\[describe-mode] in the shell buffer for a list of commands.)" - (interactive) - (if (not (term-check-proc "*shell*")) - (let* ((prog (or explicit-shell-file-name - (getenv "ESHELL") - (getenv "SHELL") - "/bin/sh")) - (name (file-name-nondirectory prog)) - (startfile (concat "~/.emacs_" name)) - (xargs-name (intern-soft (concat "explicit-" name "-args")))) - (set-buffer (apply 'make-term "shell" prog - (if (file-exists-p startfile) startfile) - (if (and xargs-name (boundp xargs-name)) - (symbol-value xargs-name) - '("-i")))) - (tshell-mode))) - (switch-to-buffer "*shell*")) - -;;; Directory tracking -;;; =========================================================================== -;;; This code provides the tshell mode input sentinel -;;; TSHELL-DIRECTORY-TRACKER -;;; that tracks cd, pushd, and popd commands issued to the tshell, and -;;; changes the current directory of the tshell buffer accordingly. -;;; -;;; A better mechanism is now available: -;;; The standard term process filter supports a special escape command -;;; \032 / \n -;;; that the inferior can use to tell emacs what the current working -;;; directory is. -;;; All the inferior has to do is something like: -;;; printf("\032/%s\n", PWD); -;;; Most modern shells can be programmed to emit this string easily. -;;; Hopefully, bash (at least) will be modified to do this automatically. -;;; -;;; So all this horrible directory-tracking machinary is now obsolete, -;;; but is kept at least until the standard GNU shells are modified -;;; -;;; This is basically a fragile hack, although it's more accurate than -;;; the version in Emacs 18's shell.el. It has the following failings: -;;; 1. It doesn't know about the cdpath shell variable. -;;; 2. It cannot infallibly deal with command sequences, though it does well -;;; with these and with ignoring commands forked in another shell with ()s. -;;; 3. More generally, any complex command is going to throw it. Otherwise, -;;; you'd have to build an entire shell interpreter in emacs lisp. Failing -;;; that, there's no way to catch shell commands where cd's are buried -;;; inside conditional expressions, aliases, and so forth. -;;; -;;; The whole approach is a crock. Shell aliases mess it up. File sourcing -;;; messes it up. You run other processes under the shell; these each have -;;; separate working directories, and some have commands for manipulating -;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have -;;; commands that do *not* affect the current w.d. at all, but look like they -;;; do (e.g., the cd command in ftp). In shells that allow you job -;;; control, you can switch between jobs, all having different w.d.'s. So -;;; simply saying %3 can shift your w.d.. -;;; -;;; The solution is to relax, not stress out about it, and settle for -;;; a hack that works pretty well in typical circumstances. Remember -;;; that a half-assed solution is more in keeping with the spirit of Unix, -;;; anyway. Blech. - -(defun tshell-directory-tracker (str) - "Tracks cd, pushd and popd commands issued to the shell. -This function is called on each input passed to the shell. -It watches for cd, pushd and popd commands and sets the buffer's -default directory to track these commands. - -You may toggle this tracking on and off with M-x dirtrack-toggle. -If emacs gets confused, you can resync with the shell with M-x dirs. - -See variables `shell-cd-regexp', `shell-pushd-regexp', and `shell-popd-regexp', -while `shell-pushd-tohome', `shell-pushd-dextract' and `shell-pushd-dunique' -control the behavior of the relevant command. - -Environment variables are expanded, see function `substitute-in-file-name'." - (if tshell-dirtrackp - ;; We fail gracefully if we think the command will fail in the shell. - (condition-case chdir-failure - (let ((start (progn (string-match "^[;\\s ]*" str) ; skip whitespace - (match-end 0))) - end cmd arg1) - (while (string-match shell-command-regexp str start) - (setq end (match-end 0) - cmd (term-arguments (substring str start end) 0 0) - arg1 (term-arguments (substring str start end) 1 1)) - (cond ((eq (string-match shell-popd-regexp cmd) 0) - (tshell-process-popd (substitute-in-file-name arg1))) - ((eq (string-match shell-pushd-regexp cmd) 0) - (tshell-process-pushd (substitute-in-file-name arg1))) - ((eq (string-match shell-cd-regexp cmd) 0) - (tshell-process-cd (substitute-in-file-name arg1)))) - (setq start (progn (string-match "[;\\s ]*" str end) ; skip again - (match-end 0))))) - (error "Couldn't cd")))) - -;;; popd [+n] -(defun tshell-process-popd (arg) - (let ((num (or (tshell-extract-num arg) 0))) - (cond ((and num (= num 0) tshell-dirstack) - (cd (car tshell-dirstack)) - (setq tshell-dirstack (cdr tshell-dirstack)) - (tshell-dirstack-message)) - ((and num (> num 0) (<= num (length tshell-dirstack))) - (let* ((ds (cons nil tshell-dirstack)) - (cell (nthcdr (1- num) ds))) - (rplacd cell (cdr (cdr cell))) - (setq tshell-dirstack (cdr ds)) - (tshell-dirstack-message))) - (t - (error "Couldn't popd"))))) - -;; Return DIR prefixed with term-file-name-prefix as appropriate. -(defun tshell-prefixed-directory-name (dir) - (if (= (length term-file-name-prefix) 0) - dir - (if (file-name-absolute-p dir) - ;; The name is absolute, so prepend the prefix. - (concat term-file-name-prefix dir) - ;; For a relative name we assume default-directory already has the prefix. - (expand-file-name dir)))) - -;;; cd [dir] -(defun tshell-process-cd (arg) - (let ((new-dir (cond ((zerop (length arg)) (concat term-file-name-prefix - "~")) - ((string-equal "-" arg) tshell-last-dir) - (t (tshell-prefixed-directory-name arg))))) - (setq tshell-last-dir default-directory) - (cd new-dir) - (tshell-dirstack-message))) - -;;; pushd [+n | dir] -(defun tshell-process-pushd (arg) - (let ((num (tshell-extract-num arg))) - (cond ((zerop (length arg)) - ;; no arg -- swap pwd and car of stack unless shell-pushd-tohome - (cond (shell-pushd-tohome - (shell-process-pushd (concat term-file-name-prefix "~"))) - (tshell-dirstack - (let ((old default-directory)) - (cd (car tshell-dirstack)) - (setq tshell-dirstack - (cons old (cdr tshell-dirstack))) - (tshell-dirstack-message))) - (t - (message "Directory stack empty.")))) - ((numberp num) - ;; pushd +n - (cond ((> num (length tshell-dirstack)) - (message "Directory stack not that deep.")) - ((= num 0) - (error (message "Couldn't cd."))) - (shell-pushd-dextract - (let ((dir (nth (1- num) tshell-dirstack))) - (tshell-process-popd arg) - (tshell-process-pushd default-directory) - (cd dir) - (tshell-dirstack-message))) - (t - (let* ((ds (cons default-directory tshell-dirstack)) - (dslen (length ds)) - (front (nthcdr num ds)) - (back (reverse (nthcdr (- dslen num) (reverse ds)))) - (new-ds (append front back))) - (cd (car new-ds)) - (setq tshell-dirstack (cdr new-ds)) - (tshell-dirstack-message))))) - (t - ;; pushd - (let ((old-wd default-directory)) - (cd (tshell-prefixed-directory-name arg)) - (if (or (null shell-pushd-dunique) - (not (member old-wd tshell-dirstack))) - (setq tshell-dirstack (cons old-wd tshell-dirstack))) - (tshell-dirstack-message)))))) - -;; If STR is of the form +n, for n>0, return n. Otherwise, nil. -(defun tshell-extract-num (str) - (and (string-match "^\\+[1-9][0-9]*$" str) - (string-to-int str))) - - -(defun tshell-dirtrack-toggle () - "Turn directory tracking on and off in a shell buffer." - (interactive) - (setq tshell-dirtrackp (not tshell-dirtrackp)) - (message "Directory tracking %s" (if tshell-dirtrackp "ON" "OFF"))) - -;;; For your typing convenience: -(defalias 'dirtrack-toggle 'tshell-dirtrack-toggle) - - -(defun tshell-resync-dirs () - "Resync the buffer's idea of the current directory stack. -This command queries the shell with the command bound to -`tshell-dirstack-query' (default \"dirs\"), reads the next -line output and parses it to form the new directory stack. -DON'T issue this command unless the buffer is at a shell prompt. -Also, note that if some other subprocess decides to do output -immediately after the query, its output will be taken as the -new directory stack -- you lose. If this happens, just do the -command again." - (interactive) - (let* ((proc (get-buffer-process (current-buffer))) - (pmark (process-mark proc))) - (goto-char pmark) - (insert tshell-dirstack-query) (insert "\n") - (sit-for 0) ; force redisplay - (term-send-string proc tshell-dirstack-query) - (term-send-string proc "\n") - (set-marker pmark (point)) - (let ((pt (point))) ; wait for 1 line - ;; This extra newline prevents the user's pending input from spoofing us. - (insert "\n") (backward-char 1) - (while (not (looking-at ".+\n")) - (accept-process-output proc) - (goto-char pt))) - (goto-char pmark) (delete-char 1) ; remove the extra newline - ;; That's the dirlist. grab it & parse it. - (let* ((dl (buffer-substring (match-beginning 0) (1- (match-end 0)))) - (dl-len (length dl)) - (ds '()) ; new dir stack - (i 0)) - (while (< i dl-len) - ;; regexp = optional whitespace, (non-whitespace), optional whitespace - (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir - (setq ds (cons (concat term-file-name-prefix - (substring dl (match-beginning 1) - (match-end 1))) - ds)) - (setq i (match-end 0))) - (let ((ds (nreverse ds))) - (condition-case nil - (progn (cd (car ds)) - (setq tshell-dirstack (cdr ds)) - (tshell-dirstack-message)) - (error (message "Couldn't cd."))))))) - -;;; For your typing convenience: -(defalias 'dirs 'tshell-resync-dirs) - - -;;; Show the current dirstack on the message line. -;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo". -;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".) -;;; All the commands that mung the buffer's dirstack finish by calling -;;; this guy. -(defun tshell-dirstack-message () - (let* ((msg "") - (ds (cons default-directory tshell-dirstack)) - (home (expand-file-name (concat term-file-name-prefix "~/"))) - (homelen (length home))) - (while ds - (let ((dir (car ds))) - (and (>= (length dir) homelen) (string= home (substring dir 0 homelen)) - (setq dir (concat "~/" (substring dir homelen)))) - ;; Strip off term-file-name-prefix if present. - (and term-file-name-prefix - (>= (length dir) (length term-file-name-prefix)) - (string= term-file-name-prefix - (substring dir 0 (length term-file-name-prefix))) - (setq dir (substring dir (length term-file-name-prefix))) - (setcar ds dir)) - (setq msg (concat msg (directory-file-name dir) " ")) - (setq ds (cdr ds)))) - (message msg))) - -(defun tshell-forward-command (&optional arg) - "Move forward across ARG shell command(s). Does not cross lines. -See `shell-command-regexp'." - (interactive "p") - (let ((limit (save-excursion (end-of-line nil) (point)))) - (if (re-search-forward (concat shell-command-regexp "\\([;&|][\t ]*\\)+") - limit 'move arg) - (skip-syntax-backward " ")))) - - -(defun tshell-backward-command (&optional arg) - "Move backward across ARG shell command(s). Does not cross lines. -See `shell-command-regexp'." - (interactive "p") - (let ((limit (save-excursion (term-bol nil) (point)))) - (if (> limit (point)) - (save-excursion (beginning-of-line) (setq limit (point)))) - (skip-syntax-backward " " limit) - (if (re-search-backward - (format "[;&|]+[\t ]*\\(%s\\)" shell-command-regexp) limit 'move arg) - (progn (goto-char (match-beginning 1)) - (skip-chars-forward ";&|"))))) - - -(defun tshell-dynamic-complete-command () - "Dynamically complete the command at point. -This function is similar to `term-dynamic-complete-filename', except that it -searches `exec-path' (minus the trailing emacs library path) for completion -candidates. Note that this may not be the same as the shell's idea of the -path. - -Completion is dependent on the value of `shell-completion-execonly', plus -those that effect file completion. See `tshell-dynamic-complete-as-command'. - -Returns t if successful." - (interactive) - (let ((filename (term-match-partial-filename))) - (if (and filename - (save-match-data (not (string-match "[~/]" filename))) - (eq (match-beginning 0) - (save-excursion (tshell-backward-command 1) (point)))) - (prog2 (message "Completing command name...") - (tshell-dynamic-complete-as-command))))) - - -(defun tshell-dynamic-complete-as-command () - "Dynamically complete at point as a command. -See `tshell-dynamic-complete-filename'. Returns t if successful." - (let* ((filename (or (term-match-partial-filename) "")) - (pathnondir (file-name-nondirectory filename)) - (paths (cdr (reverse exec-path))) - (cwd (file-name-as-directory (expand-file-name default-directory))) - (ignored-extensions - (and term-completion-fignore - (mapconcat (function (lambda (x) (concat (regexp-quote x) "$"))) - term-completion-fignore "\\|"))) - (path "") (comps-in-path ()) (file "") (filepath "") (completions ())) - ;; Go thru each path in the search path, finding completions. - (while paths - (setq path (file-name-as-directory (term-directory (or (car paths) "."))) - comps-in-path (and (file-accessible-directory-p path) - (file-name-all-completions pathnondir path))) - ;; Go thru each completion found, to see whether it should be used. - (while comps-in-path - (setq file (car comps-in-path) - filepath (concat path file)) - (if (and (not (member file completions)) - (not (and ignored-extensions - (string-match ignored-extensions file))) - (or (string-equal path cwd) - (not (file-directory-p filepath))) - (or (null shell-completion-execonly) - (file-executable-p filepath))) - (setq completions (cons file completions))) - (setq comps-in-path (cdr comps-in-path))) - (setq paths (cdr paths))) - ;; OK, we've got a list of completions. - (let ((success (let ((term-completion-addsuffix nil)) - (term-dynamic-simple-complete pathnondir completions)))) - (if (and (memq success '(sole shortest)) term-completion-addsuffix - (not (file-directory-p (term-match-partial-filename)))) - (insert " ")) - success))) - - -(defun tshell-match-partial-variable () - "Return the variable at point, or nil if non is found." - (save-excursion - (let ((limit (point))) - (if (re-search-backward "[^A-Za-z0-9_{}]" nil 'move) - (or (looking-at "\\$") (forward-char 1))) - ;; Anchor the search forwards. - (if (or (eolp) (looking-at "[^A-Za-z0-9_{}$]")) - nil - (re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit) - (buffer-substring (match-beginning 0) (match-end 0)))))) - - -(defun tshell-dynamic-complete-environment-variable () - "Dynamically complete the environment variable at point. -Completes if after a variable, i.e., if it starts with a \"$\". -See `tshell-dynamic-complete-as-environment-variable'. - -This function is similar to `term-dynamic-complete-filename', except that it -searches `process-environment' for completion candidates. Note that this may -not be the same as the interpreter's idea of variable names. The main problem -with this type of completion is that `process-environment' is the environment -which Emacs started with. Emacs does not track changes to the environment made -by the interpreter. Perhaps it would be more accurate if this function was -called `tshell-dynamic-complete-process-environment-variable'. - -Returns non-nil if successful." - (interactive) - (let ((variable (tshell-match-partial-variable))) - (if (and variable (string-match "^\\$" variable)) - (prog2 (message "Completing variable name...") - (tshell-dynamic-complete-as-environment-variable))))) - - -(defun tshell-dynamic-complete-as-environment-variable () - "Dynamically complete at point as an environment variable. -Used by `tshell-dynamic-complete-environment-variable'. -Uses `term-dynamic-simple-complete'." - (let* ((var (or (tshell-match-partial-variable) "")) - (variable (substring var (or (string-match "[^$({]\\|$" var) 0))) - (variables (mapcar (function (lambda (x) - (substring x 0 (string-match "=" x)))) - process-environment)) - (addsuffix term-completion-addsuffix) - (term-completion-addsuffix nil) - (success (term-dynamic-simple-complete variable variables))) - (if (memq success '(sole shortest)) - (let* ((var (tshell-match-partial-variable)) - (variable (substring var (string-match "[^$({]" var))) - (protection (cond ((string-match "{" var) "}") - ((string-match "(" var) ")") - (t ""))) - (suffix (cond ((null addsuffix) "") - ((file-directory-p - (term-directory (getenv variable))) "/") - (t " ")))) - (insert protection suffix))) - success)) - - -(defun tshell-replace-by-expanded-directory () - "Expand directory stack reference before point. -Directory stack references are of the form \"=digit\" or \"=-\". -See `default-directory' and `tshell-dirstack'. - -Returns t if successful." - (interactive) - (if (term-match-partial-filename) - (save-excursion - (goto-char (match-beginning 0)) - (let ((stack (cons default-directory tshell-dirstack)) - (index (cond ((looking-at "=-/?") - (length tshell-dirstack)) - ((looking-at "=\\([0-9]+\\)") - (string-to-number - (buffer-substring - (match-beginning 1) (match-end 1))))))) - (cond ((null index) - nil) - ((>= index (length stack)) - (error "Directory stack not that deep.")) - (t - (replace-match (file-name-as-directory (nth index stack)) t t) - (message "Directory item: %d" index) - t)))))) - -(provide 'tshell) - -;;; tshell.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/events.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/events.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,160 @@ +;;; events.el --- event functions for XEmacs. + +;; Copyright (C) 1997 Free Software Foundation, Inc. +;; Copyright (C) 1996-7 Sun Microsystems, Inc. +;; Copyright (C) 1996 Ben Wing. + +;; Maintainer: Martin Buchholz +;; Keywords: internal, event, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + + +(defun event-console (event) + "Return the console that EVENT occurred on. +This will be nil for some types of events (e.g. eval events)." + (cdfw-console (event-channel event))) + +(defun event-device (event) + "Return the device that EVENT occurred on. +This will be nil for some types of events (e.g. keyboard and eval events)." + (dfw-device (event-channel event))) + +(defun event-frame (event) + "Return the frame that EVENT occurred on. +This will be nil for some types of events (e.g. keyboard and eval events)." + (fw-frame (event-channel event))) + +(defun event-buffer (event) + "Return the buffer of the window over which mouse event EVENT occurred. +Return nil unless both (mouse-event-p EVENT) and +(event-over-text-area-p EVENT) are non-nil." + (let ((window (event-window event))) + (and (windowp window) (window-buffer window)))) + +(defalias 'allocate-event 'make-event) + + +(defun key-press-event-p (object) + "Return t if OBJECT is a key-press event." + (and (event-live-p object) (eq 'key-press (event-type object)))) + +(defun button-press-event-p (object) + "Return t if OBJECT is a mouse button-press event." + (and (event-live-p object) (eq 'button-press (event-type object)))) + +(defun button-release-event-p (object) + "Return t if OBJECT is a mouse button-release event." + (and (event-live-p object) (eq 'button-release (event-type object)))) + +(defun button-event-p (object) + "Return t if OBJECT is a mouse button-press or button-release event." + (and (event-live-p object) + (memq (event-type object) '(button-press button-release)) + t)) + +(defun motion-event-p (object) + "Return t if OBJECT is a mouse motion event." + (and (event-live-p object) (eq 'motion (event-type object)))) + +(defun mouse-event-p (object) + "Return t if OBJECT is a mouse button-press, button-release or motion event." + (and (event-live-p object) + (memq (event-type object) '(button-press button-release motion)) + t)) + +(defun process-event-p (object) + "Return t if OBJECT is a process-output event." + (and (event-live-p object) (eq 'process (event-type object)))) + +(defun timeout-event-p (object) + "Return t if OBJECT is a timeout event." + (and (event-live-p object) (eq 'timeout (event-type object)))) + +(defun eval-event-p (object) + "Return t if OBJECT is an eval event." + (and (event-live-p object) (eq 'eval (event-type object)))) + +(defun misc-user-event-p (object) + "Return t if OBJECT is a misc-user event. +A misc-user event is a user event that is not a keypress or mouse click; +normally this means a menu selection or scrollbar action." + (and (event-live-p object) (eq 'misc-user (event-type object)))) + +;; You could just as easily use event-glyph but we include this for +;; consistency. + +(defun event-over-glyph-p (object) + "Return t if OBJECT is a mouse event occurring over a glyph. +Mouse events are events of type button-press, button-release or motion." + (and (event-live-p object) (event-glyph object) t)) + +(defun keyboard-translate (&rest pairs) + "Translate character or keysym FROM to TO at a low level. +Multiple FROM-TO pairs may be specified. + +See `keyboard-translate-table' for more information." + (while pairs + (puthash (pop pairs) (pop pairs) keyboard-translate-table))) + +(put 'backspace 'ascii-character ?\b) +(put 'delete 'ascii-character ?\177) +(put 'tab 'ascii-character ?\t) +(put 'linefeed 'ascii-character ?\n) +(put 'clear 'ascii-character 12) +(put 'return 'ascii-character ?\r) +(put 'escape 'ascii-character ?\e) +(put 'space 'ascii-character ? ) + + ;; Do the same voodoo for the keypad keys. I used to bind these to keyboard + ;; macros (for instance, kp-0 was bound to "0") so that they would track the + ;; bindings of the corresponding keys by default, but that made the display + ;; of M-x describe-bindings much harder to read, so now we'll just bind them + ;; to self-insert by default. Not a big difference... + +(put 'kp-0 'ascii-character ?0) +(put 'kp-1 'ascii-character ?1) +(put 'kp-2 'ascii-character ?2) +(put 'kp-3 'ascii-character ?3) +(put 'kp-4 'ascii-character ?4) +(put 'kp-5 'ascii-character ?5) +(put 'kp-6 'ascii-character ?6) +(put 'kp-7 'ascii-character ?7) +(put 'kp-8 'ascii-character ?8) +(put 'kp-9 'ascii-character ?9) + +(put 'kp-space 'ascii-character ? ) +(put 'kp-tab 'ascii-character ?\t) +(put 'kp-enter 'ascii-character ?\r) +(put 'kp-equal 'ascii-character ?=) +(put 'kp-multiply 'ascii-character ?*) +(put 'kp-add 'ascii-character ?+) +(put 'kp-separator 'ascii-character ?,) +(put 'kp-subtract 'ascii-character ?-) +(put 'kp-decimal 'ascii-character ?.) +(put 'kp-divide 'ascii-character ?/) + +;;; events.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/extents.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/extents.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,98 @@ +;;; extents.el --- miscellaneous extent functions not written in C + +;; Copyright (C) 1993-4, 1997 Free Software Foundation, Inc. + +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;; some help from stig@hackvan.com here. + +;;; Code: + +;; an alternative to map-extents. +(defun mapcar-extents (function &optional predicate buffer-or-string from to + flags property value) + "Applies FUNCTION to all extents which overlap a region in BUFFER-OR-STRING. +The region is delimited by FROM and TO. FUNCTION is called with +one argument, the extent. A list of the values returned by FUNCTION +is returned. An optional PREDICATE may be used to further limit the +extents over which FUNCTION is mapped. The optional arguments FLAGS, +PROPERTY, and VALUE may also be used to control the extents passed to +PREDICATE or FUNCTION. See also `map-extents'." + (let (*result*) + (map-extents (if predicate + #'(lambda (ex junk) + (and (funcall predicate ex) + (setq *result* (cons (funcall function ex) + *result*))) + nil) + #'(lambda (ex junk) + (setq *result* (cons (funcall function ex) + *result*)) + nil)) + buffer-or-string from to nil flags property value) + (nreverse *result*))) + +(defun extent-list (&optional buffer-or-string from to flags) + "Return a list of the extents in BUFFER-OR-STRING. +BUFFER-OR-STRING defaults to the current buffer if omitted. +FROM and TO can be used to limit the range over which extents are +returned; if omitted, all extents in the buffer or string are returned. + +More specifically, if a range is specified using FROM and TO, only +extents that overlap the range (i.e. begin or end inside of the range) +are included in the list. FROM and TO default to the beginning and +end of BUFFER-OR-STRING, respectively. + +FLAGS controls how end cases are treated. For a discussion of this, +and exactly what ``overlap'' means, see `map-extents'. + +If you want to map a function over the extents in a buffer or string, +consider using `map-extents' or `mapcar-extents' instead." + (mapcar-extents 'identity nil buffer-or-string from to flags)) + +(defun extent-string (extent) + "Return the string delimited by the bounds of EXTENT." + (let ((object (extent-object extent))) + (if (bufferp object) + (buffer-substring (extent-start-position extent) + (extent-end-position extent) + object) + (substring object + (extent-start-position extent) + (extent-end-position extent))))) + +(defun extent-descendants (extent) + "Return a list of all descendants of EXTENT, including EXTENT. +This recursively applies `extent-children' to any children of +EXTENT, until no more children can be found." + (let ((children (extent-children extent))) + (if children + (apply 'nconc (mapcar 'extent-descendants children)) + (list extent)))) + +(defun set-extent-keymap (extent keymap) + "Set EXTENT's `keymap' property to KEYMAP." + (set-extent-property extent 'keymap keymap)) + +;;; extents.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/faces.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/faces.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,1692 @@ +;;; faces.el --- Lisp interface to the C "face" structure + +;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995 Board of Trustees, University of Illinois +;; Copyright (C) 1995, 1996 Ben Wing + +;; Author: Ben Wing +;; Keywords: faces, internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not synched with FSF. Almost completely divergent. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; face implementation #1 (used Lisp vectors and parallel C vectors; +;; FSFmacs still uses this) authored by Jamie Zawinski +;; pre Lucid-Emacs 19.0. + +;; face implementation #2 (used one face object per frame per face) +;; authored by Jamie Zawinski for 19.9. + +;; face implementation #3 (use one face object per face) originally +;; authored for 19.12 by Chuck Thompson , +;; rewritten by Ben Wing with the advent of specifiers. + + +;;; Some stuff in FSF's faces.el is in our x-faces.el. + +;;; Code: + +(defun read-face-name (prompt) + (let (face) + (while (= (length face) 0) ; nil or "" + (setq face (completing-read prompt + (mapcar (lambda (x) (list (symbol-name x))) + (face-list)) + nil t))) + (intern face))) + +(defun face-interactive (what &optional bool) + (let* ((fn (intern (concat "face-" what "-instance"))) + (face (read-face-name (format "Set %s of face: " what))) + (default (if (fboundp fn) + ;; #### we should distinguish here between + ;; explicitly setting the value to be the + ;; same as the default face's value, and + ;; not setting a value at all. + (funcall fn face))) + (value (if bool + (y-or-n-p (format "Should face %s be %s? " + (symbol-name face) bool)) + (read-string (format "Set %s of face %s to: " + what (symbol-name face)) + (cond ((font-instance-p default) + (font-instance-name default)) + ((color-instance-p default) + (color-instance-name default)) + ((image-instance-p default) + (image-instance-file-name default)) + (t default)))))) + (list face (if (equal value "") nil value)))) + +(defconst built-in-face-specifiers + (built-in-face-specifiers) + "A list of the built-in face properties that are specifiers.") + +(defun face-property (face property &optional locale tag-set exact-p) + "Return FACE's value of the given PROPERTY. + +If LOCALE is omitted, the FACE's actual value for PROPERTY will be + returned. For built-in properties, this will be a specifier object + of a type appropriate to the property (e.g. a font or color + specifier). For other properties, this could be anything. + +If LOCALE is supplied, then instead of returning the actual value, + the specification(s) for the given locale or locale type will + be returned. This will only work if the actual value of + PROPERTY is a specifier (this will always be the case for built-in + properties, but not or not may apply to user-defined properties). + If the actual value of PROPERTY is not a specifier, this value + will simply be returned regardless of LOCALE. + +The return value will be a list of instantiators (e.g. strings + specifying a font or color name), or a list of specifications, each + of which is a cons of a locale and a list of instantiators. + Specifically, if LOCALE is a particular locale (a buffer, window, + frame, device, or 'global), a list of instantiators for that locale + will be returned. Otherwise, if LOCALE is a locale type (one of + the symbols 'buffer, 'window, 'frame, or 'device), the specifications + for all locales of that type will be returned. Finally, if LOCALE is + 'all, the specifications for all locales of all types will be returned. + +The specifications in a specifier determine what the value of + PROPERTY will be in a particular \"domain\" or set of circumstances, + which is typically a particular Emacs window along with the buffer + it contains and the frame and device it lies within. The value + is derived from the instantiator associated with the most specific + locale (in the order buffer, window, frame, device, and 'global) + that matches the domain in question. In other words, given a domain + (i.e. an Emacs window, usually), the specifier for PROPERTY will first + be searched for a specification whose locale is the buffer contained + within that window; then for a specification whose locale is the window + itself; then for a specification whose locale is the frame that the + window is contained within; etc. The first instantiator that is + valid for the domain (usually this means that the instantiator is + recognized by the device [i.e. the X server or TTY device] that the + domain is on. The function `face-property-instance' actually does + all this, and is used to determine how to display the face. + +See `set-face-property' for the built-in property-names." + + (setq face (get-face face)) + (let ((value (get face property))) + (if (and locale + (or (memq property built-in-face-specifiers) + (specifierp value))) + (setq value (specifier-specs value locale tag-set exact-p))) + value)) + +(defun convert-face-property-into-specifier (face property) + "Convert PROPERTY on FACE into a specifier, if it's not already." + (setq face (get-face face)) + (let ((specifier (get face property))) + ;; if a user-property does not have a specifier but a + ;; locale was specified, put a specifier there. + ;; If there was already a value there, convert it to a + ;; specifier with the value as its 'global instantiator. + (unless (specifierp specifier) + (let ((new-specifier (make-specifier 'generic))) + (if (or (not (null specifier)) + ;; make sure the nil returned from `get' wasn't + ;; actually the value of the property + (null (get face property t))) + (add-spec-to-specifier new-specifier specifier)) + (setq specifier new-specifier) + (put face property specifier))))) + +(defun face-property-instance (face property + &optional domain default no-fallback) + "Return the instance of FACE's PROPERTY in the specified DOMAIN. + +Under most circumstances, DOMAIN will be a particular window, + and the returned instance describes how the specified property + actually is displayed for that window and the particular buffer + in it. Note that this may not be the same as how the property + appears when the buffer is displayed in a different window or + frame, or how the property appears in the same window if you + switch to another buffer in that window; and in those cases, + the returned instance would be different. + +The returned instance will typically be a color-instance, + font-instance, or pixmap-instance object, and you can query + it using the appropriate object-specific functions. For example, + you could use `color-instance-rgb-components' to find out the + RGB (red, green, and blue) components of how the 'background + property of the 'highlight face is displayed in a particular + window. The results might be different from the results + you would get for another window (perhaps the user + specified a different color for the frame that window is on; + or perhaps the same color was specified but the window is + on a different X server, and that X server has different RGB + values for the color from this one). + +DOMAIN defaults to the selected window if omitted. + +DOMAIN can be a frame or device, instead of a window. The value + returned for a such a domain is used in special circumstances + when a more specific domain does not apply; for example, a frame + value might be used for coloring a toolbar, which is conceptually + attached to a frame rather than a particular window. The value + is also useful in determining what the value would be for a + particular window within the frame or device, if it is not + overridden by a more specific specification. + +If PROPERTY does not name a built-in property, its value will + simply be returned unless it is a specifier object, in which case + it will be instanced using `specifier-instance'. + +Optional arguments DEFAULT and NO-FALLBACK are the same as in + `specifier-instance'." + + (setq face (get-face face)) + (let ((value (get face property))) + (if (specifierp value) + (setq value (specifier-instance value domain default no-fallback))) + value)) + +(defun face-property-matching-instance (face property matchspec + &optional domain default + no-fallback) + "Return the instance of FACE's PROPERTY matching MATCHSPEC in DOMAIN. +Currently the only useful value for MATCHSPEC is a charset, when used +in conjunction with the face's font; this allows you to retrieve a +font that can be used to display a particular charset, rather than just +any font. + +Other than MATCHSPEC, this function is identical to `face-property-instance'. +See also `specifier-matching-instance' for a fuller description of the +matching process." + + (setq face (get-face face)) + (let ((value (get face property))) + (if (specifierp value) + (setq value (specifier-matching-instance value matchspec domain + default no-fallback))) + value)) + +(defun set-face-property (face property value &optional locale tag-set + how-to-add) + "Change a property of a FACE. + +NOTE: If you want to remove a property from a face, use `remove-face-property' + rather than attempting to set a value of nil for the property. + +For built-in properties, the actual value of the property is a + specifier and you cannot change this; but you can change the + specifications within the specifier, and that is what this function + will do. For user-defined properties, you can use this function + to either change the actual value of the property or, if this value + is a specifier, change the specifications within it. + +If PROPERTY is a built-in property, the specifications to be added to + this property can be supplied in many different ways: + + -- If VALUE is a simple instantiator (e.g. a string naming a font or + color) or a list of instantiators, then the instantiator(s) will + be added as a specification of the property for the given LOCALE + (which defaults to 'global if omitted). + -- If VALUE is a list of specifications (each of which is a cons of + a locale and a list of instantiators), then LOCALE must be nil + (it does not make sense to explicitly specify a locale in this + case), and specifications will be added as given. + -- If VALUE is a specifier (as would be returned by `face-property' + if no LOCALE argument is given), then some or all of the + specifications in the specifier will be added to the property. + In this case, the function is really equivalent to + `copy-specifier' and LOCALE has the same semantics (if it is + a particular locale, the specification for the locale will be + copied; if a locale type, specifications for all locales of + that type will be copied; if nil or 'all, then all + specifications will be copied). + +HOW-TO-ADD should be either nil or one of the symbols 'prepend, + 'append, 'remove-tag-set-prepend, 'remove-tag-set-append, 'remove-locale, + 'remove-locale-type, or 'remove-all. See `copy-specifier' and + `add-spec-to-specifier' for a description of what each of + these means. Most of the time, you do not need to worry about + this argument; the default behavior usually is fine. + +In general, it is OK to pass an instance object (e.g. as returned + by `face-property-instance') as an instantiator in place of + an actual instantiator. In such a case, the instantiator used + to create that instance object will be used (for example, if + you set a font-instance object as the value of the 'font + property, then the font name used to create that object will + be used instead). If some cases, however, doing this + conversion does not make sense, and this will be noted in + the documentation for particular types of instance objects. + +If PROPERTY is not a built-in property, then this function will + simply set its value if LOCALE is nil. However, if LOCALE is + given, then this function will attempt to add VALUE as the + instantiator for the given LOCALE, using `add-spec-to-specifier'. + If the value of the property is not a specifier, it will + automatically be converted into a 'generic specifier. + + +The following symbols have predefined meanings: + + foreground The foreground color of the face. + For valid instantiators, see `color-specifier-p'. + + background The background color of the face. + For valid instantiators, see `color-specifier-p'. + + font The font used to display text covered by this face. + For valid instantiators, see `font-specifier-p'. + + display-table The display table of the face. + This should be a vector of 256 elements. + + background-pixmap The pixmap displayed in the background of the face. + Only used by faces on X devices. + For valid instantiators, see `image-specifier-p'. + + underline Underline all text covered by this face. + For valid instantiators, see `face-boolean-specifier-p'. + + strikethru Draw a line through all text covered by this face. + For valid instantiators, see `face-boolean-specifier-p'. + + highlight Highlight all text covered by this face. + Only used by faces on TTY devices. + For valid instantiators, see `face-boolean-specifier-p'. + + dim Dim all text covered by this face. + Only used by faces on TTY devices. + For valid instantiators, see `face-boolean-specifier-p'. + + blinking Blink all text covered by this face. + Only used by faces on TTY devices. + For valid instantiators, see `face-boolean-specifier-p'. + + reverse Reverse the foreground and background colors. + Only used by faces on TTY devices. + For valid instantiators, see `face-boolean-specifier-p'. + + doc-string Description of what the face's normal use is. + NOTE: This is not a specifier, unlike all + the other built-in properties, and cannot + contain locale-specific values." + + (setq face (get-face face)) + (if (memq property built-in-face-specifiers) + (set-specifier (get face property) value locale tag-set how-to-add) + + ;; This section adds user defined properties. + (if (not locale) + (put face property value) + (convert-face-property-into-specifier face property) + (add-spec-to-specifier (get face property) value locale tag-set + how-to-add))) + value) + +(defun remove-face-property (face property &optional locale tag-set exact-p) + "Remove a property from a face. +For built-in properties, this is analogous to `remove-specifier'. +See `remove-specifier' for the meaning of the LOCALE, TAG-SET, and EXACT-P +arguments." + (or locale (setq locale 'all)) + (if (memq property built-in-face-specifiers) + (remove-specifier (face-property face property) locale tag-set exact-p) + (if (eq locale 'all) + (remprop (get-face face) property) + (convert-face-property-into-specifier face property) + (remove-specifier (face-property face property) locale tag-set + exact-p)))) + +(defun reset-face (face &optional locale tag-set exact-p) + "Clear all existing built-in specifications from FACE. +This makes FACE inherit all its display properties from 'default. +WARNING: Be absolutely sure you want to do this!!! It is a dangerous +operation and is not undoable. + +The arguments LOCALE, TAG-SET and EXACT-P are the same as for +`remove-specifier'." + (mapc (lambda (x) + (remove-specifier (face-property face x) locale tag-set exact-p)) + built-in-face-specifiers) + nil) + +(defun set-face-parent (face parent &optional locale tag-set how-to-add) + "Set the parent of FACE to PARENT, for all properties. +This makes all properties of FACE inherit from PARENT." + (setq parent (get-face parent)) + (mapcar (lambda (x) + (set-face-property face x (vector parent) locale tag-set + how-to-add)) + (delq 'display-table + (delq 'background-pixmap + (copy-sequence built-in-face-specifiers)))) + (set-face-background-pixmap face (vector 'inherit ':face parent) + locale tag-set how-to-add) + nil) + +(defun face-doc-string (face) + "Return the documentation string for FACE." + (face-property face 'doc-string)) + +(defun set-face-doc-string (face doc-string) + "Change the documentation string of FACE to DOC-STRING." + (interactive (face-interactive "doc-string")) + (set-face-property face 'doc-string doc-string)) + +(defun face-font-name (face &optional domain charset) + "Return the font name of the given face, or nil if it is unspecified. +DOMAIN is as in `face-font-instance'." + (let ((f (face-font-instance face domain charset))) + (and f (font-instance-name f)))) + +(defun face-font (face &optional locale tag-set exact-p) + "Return the font of the given face, or nil if it is unspecified. + +FACE may be either a face object or a symbol representing a face. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `face-property' for more information." + (face-property face 'font locale tag-set exact-p)) + +(defun face-font-instance (face &optional domain charset) + "Return the instance of the given face's font in the given domain. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the font appears in that + particular window and buffer will be returned. + +See `face-property-instance' for more information." + (if charset + (face-property-matching-instance face 'font charset domain) + (face-property-instance face 'font domain))) + +(defun set-face-font (face font &optional locale tag-set how-to-add) + "Change the font of the given face. + +FACE may be either a face object or a symbol representing a face. + +FONT should be an instantiator (see `font-specifier-p'), a list of + instantiators, an alist of specifications (each mapping a + locale to an instantiator list), or a font specifier object. + +If FONT is an alist, LOCALE must be omitted. If FONT is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-face-property' for more information." + (interactive (face-interactive "font")) + (set-face-property face 'font font locale tag-set how-to-add)) + +(defun face-foreground (face &optional locale tag-set exact-p) + "Return the foreground of the given face, or nil if it is unspecified. + +FACE may be either a face object or a symbol representing a face. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `face-property' for more information." + (face-property face 'foreground locale tag-set exact-p)) + +(defun face-foreground-instance (face &optional domain default no-fallback) + "Return the instance of the given face's foreground in the given domain. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the foreground appears in that + particular window and buffer will be returned. + +See `face-property-instance' for more information." + (face-property-instance face 'foreground domain default no-fallback)) + +(defun face-foreground-name (face &optional domain default no-fallback) + "Return the name of the given face's foreground color in the given domain. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the background appears in that + particular window and buffer will be returned. + +See `face-property-instance' for more information." + (color-instance-name (face-foreground-instance + face domain default no-fallback))) + +(defun set-face-foreground (face color &optional locale tag-set how-to-add) + "Change the foreground of the given face. + +FACE may be either a face object or a symbol representing a face. + +COLOR should be an instantiator (see `color-specifier-p'), a list of + instantiators, an alist of specifications (each mapping a locale to + an instantiator list), or a color specifier object. + +If COLOR is an alist, LOCALE must be omitted. If COLOR is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-face-property' for more information." + (interactive (face-interactive "foreground")) + (set-face-property face 'foreground color locale tag-set how-to-add)) + +(defun face-background (face &optional locale tag-set exact-p) + "Return the background of the given face, or nil if it is unspecified. + +FACE may be either a face object or a symbol representing a face. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `face-property' for more information." + (face-property face 'background locale tag-set exact-p)) + +(defun face-background-instance (face &optional domain default no-fallback) + "Return the instance of the given face's background in the given domain. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the background appears in that + particular window and buffer will be returned. + +See `face-property-instance' for more information." + (face-property-instance face 'background domain default no-fallback)) + +(defun face-background-name (face &optional domain default no-fallback) + "Return the name of the given face's background color in the given domain. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the background appears in that + particular window and buffer will be returned. + +See `face-property-instance' for more information." + (color-instance-name (face-background-instance + face domain default no-fallback))) + +(defun set-face-background (face color &optional locale tag-set how-to-add) + "Change the background of the given face. + +FACE may be either a face object or a symbol representing a face. + +COLOR should be an instantiator (see `color-specifier-p'), a list of + instantiators, an alist of specifications (each mapping a locale to + an instantiator list), or a color specifier object. + +If COLOR is an alist, LOCALE must be omitted. If COLOR is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-face-property' for more information." + (interactive (face-interactive "background")) + (set-face-property face 'background color locale tag-set how-to-add)) + +(defun face-background-pixmap (face &optional locale tag-set exact-p) + "Return the background pixmap of the given face, or nil if it is unspecified. +This property is only used on X devices. + +FACE may be either a face object or a symbol representing a face. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `face-property' for more information." + (face-property face 'background-pixmap locale tag-set exact-p)) + +(defun face-background-pixmap-instance (face &optional domain default + no-fallback) + "Return the instance of the given face's background pixmap in the given domain. + +FACE may be either a face object or a symbol representing a face. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the background appears in that + particular window and buffer will be returned. + +See `face-property-instance' for more information." + (face-property-instance face 'background-pixmap domain default no-fallback)) + +(defun set-face-background-pixmap (face pixmap &optional locale tag-set + how-to-add) + "Change the background pixmap of the given face. +This property is only used on X devices. + +FACE may be either a face object or a symbol representing a face. + +PIXMAP should be an instantiator (see `image-specifier-p'), a list + of instantiators, an alist of specifications (each mapping a locale + to an instantiator list), or an image specifier object. + +If PIXMAP is an alist, LOCALE must be omitted. If PIXMAP is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-face-property' for more information." + (interactive (face-interactive "background-pixmap")) + (set-face-property face 'background-pixmap pixmap locale tag-set how-to-add)) + +(defun face-display-table (face &optional locale tag-set exact-p) + "Return the display table of the given face. + +A vector (as returned by `make-display-table') will be returned. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `face-property' for more information." + (face-property face 'display-table locale tag-set exact-p)) + +(defun face-display-table-instance (face &optional domain default no-fallback) + "Return the instance of FACE's display table in DOMAIN. +A vector (as returned by `make-display-table') will be returned. + +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'display-table domain default no-fallback)) + +(defun set-face-display-table (face display-table &optional locale tag-set + how-to-add) + "Change the display table of the given face. +DISPLAY-TABLE should be a vector as returned by `make-display-table'. + +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "display-table")) + (set-face-property face 'display-table display-table locale tag-set + how-to-add)) + +;; The following accessors and mutators are, IMHO, good +;; implementation. Cf. with `make-face-bold'. + +(defun face-underline-p (face &optional domain default no-fallback) + "Return whether the given face is underlined. +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'underline domain default no-fallback)) + +(defun set-face-underline-p (face underline-p &optional locale tag-set + how-to-add) + "Change whether the given face is underlined. +UNDERLINE-P is normally a face-boolean instantiator; see + `face-boolean-specifier-p'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "underline-p" "underlined")) + (set-face-property face 'underline underline-p locale tag-set how-to-add)) + +(defun face-strikethru-p (face &optional domain default no-fallback) + "Return whether the given face is strikethru-d (i.e. struck through). +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'strikethru domain default no-fallback)) + +(defun set-face-strikethru-p (face strikethru-p &optional locale tag-set + how-to-add) + "Change whether the given face is strikethru-d (i.e. struck through). +STRIKETHRU-P is normally a face-boolean instantiator; see + `face-boolean-specifier-p'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "strikethru-p" "strikethru-d")) + (set-face-property face 'strikethru strikethru-p locale tag-set how-to-add)) + +(defun face-highlight-p (face &optional domain default no-fallback) + "Return whether the given face is highlighted (TTY domains only). +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'highlight domain default no-fallback)) + +(defun set-face-highlight-p (face highlight-p &optional locale tag-set + how-to-add) + "Change whether the given face is highlighted (TTY locales only). +HIGHLIGHT-P is normally a face-boolean instantiator; see + `face-boolean-specifier-p'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "highlight-p" "highlighted")) + (set-face-property face 'highlight highlight-p locale tag-set how-to-add)) + +(defun face-dim-p (face &optional domain default no-fallback) + "Return whether the given face is dimmed (TTY domains only). +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'dim domain default no-fallback)) + +(defun set-face-dim-p (face dim-p &optional locale tag-set how-to-add) + "Change whether the given face is dimmed (TTY locales only). +DIM-P is normally a face-boolean instantiator; see + `face-boolean-specifier-p'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "dim-p" "dimmed")) + (set-face-property face 'dim dim-p locale tag-set how-to-add)) + +(defun face-blinking-p (face &optional domain default no-fallback) + "Return whether the given face is blinking (TTY domains only). +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'blinking domain default no-fallback)) + +(defun set-face-blinking-p (face blinking-p &optional locale tag-set + how-to-add) + "Change whether the given face is blinking (TTY locales only). +BLINKING-P is normally a face-boolean instantiator; see + `face-boolean-specifier-p'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "blinking-p" "blinking")) + (set-face-property face 'blinking blinking-p locale tag-set how-to-add)) + +(defun face-reverse-p (face &optional domain default no-fallback) + "Return whether the given face is reversed (TTY domains only). +See `face-property-instance' for the semantics of the DOMAIN argument." + (face-property-instance face 'reverse domain default no-fallback)) + +(defun set-face-reverse-p (face reverse-p &optional locale tag-set how-to-add) + "Change whether the given face is reversed (TTY locales only). +REVERSE-P is normally a face-boolean instantiator; see + `face-boolean-specifier-p'. +See `set-face-property' for the semantics of the LOCALE, TAG-SET, and + HOW-TO-ADD arguments." + (interactive (face-interactive "reverse-p" "reversed")) + (set-face-property face 'reverse reverse-p locale tag-set how-to-add)) + + +(defun face-property-equal (face1 face2 prop domain) + (equal (face-property-instance face1 prop domain) + (face-property-instance face2 prop domain))) + +(defun face-equal-loop (props face1 face2 domain) + (while (and props + (face-property-equal face1 face2 (car props) domain)) + (setq props (cdr props))) + (null props)) + +(defun face-equal (face1 face2 &optional domain) + "True if the given faces will display in the same way. +See `face-property-instance' for the semantics of the DOMAIN argument." + (if (null domain) (setq domain (selected-window))) + (if (not (valid-specifier-domain-p domain)) + (error "Invalid specifier domain")) + (let ((device (dfw-device domain)) + (common-props '(foreground background font display-table underline)) + (x-props '(background-pixmap strikethru)) + (tty-props '(highlight dim blinking reverse))) + + ;; First check the properties which are used in common between the + ;; x and tty devices. Then, check those properties specific to + ;; the particular device type. + (and (face-equal-loop common-props face1 face2 domain) + (cond ((eq 'tty (device-type device)) + (face-equal-loop tty-props face1 face2 domain)) + ((eq 'x (device-type device)) + (face-equal-loop x-props face1 face2 domain)) + (t t))))) + +(defun face-differs-from-default-p (face &optional domain) + "True if the given face will display differently from the default face. +See `face-property-instance' for the semantics of the DOMAIN argument." + (not (face-equal face 'default domain))) + + +;; This function is a terrible, disgusting hack!!!! Need to +;; separate out the font elements as separate face properties! + +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +;; WE DEMAND LEXICAL SCOPING!!! +(defun frob-face-property (face property func &optional locale) + "Change the specifier for FACE's PROPERTY according to FUNC, in LOCALE. +This function is ugly and messy and is primarily used as an internal +helper function for `make-face-bold' et al., so you probably don't +want to use it or read the rest of the documentation. But if you do ... + +FUNC should be a function of two arguments (an instance and a device) +that returns a modified name that is valid for the given device. +If LOCALE specifies a valid domain (i.e. a window, frame, or device), +this function instantiates the specifier over that domain, applies FUNC +to the resulting instance, and adds the result back as an instantiator +for that locale. Otherwise, LOCALE should be a locale, locale type, or +'all (defaults to 'all if omitted). For each specification thusly +included: if the locale given is a valid domain, FUNC will be +iterated over all valid instantiators for the device of the domain +until a non-nil result is found (if there is no such result, the +first valid instantiator is used), and that result substituted for +the specification; otherwise, the process just outlined is +iterated over each existing device and the concatenated results +substituted for the specification." + (let ((sp (face-property face property))) + (if (valid-specifier-domain-p locale) + ;; this is easy. + (let* ((inst (face-property-instance face property locale)) + (name (and inst (funcall func inst (dfw-device locale))))) + (when name + (add-spec-to-specifier sp name locale))) + ;; otherwise, map over all specifications ... + ;; but first, some further kludging: + ;; (1) if we're frobbing the global property, make sure + ;; that something is there (copy from the default face, + ;; if necessary). Otherwise, something like + ;; (make-face-larger 'modeline) + ;; won't do anything at all if the modeline simply + ;; inherits its font from 'default. + ;; (2) if we're frobbing a particular locale, nothing would + ;; happen if that locale has no instantiators. So signal + ;; an error to indicate this. + (if (and (or (eq locale 'global) (eq locale 'all) (not locale)) + (not (face-property face property 'global))) + (copy-specifier (face-property 'default property) + (face-property face property) + 'global)) + (if (and (valid-specifier-locale-p locale) + (not (face-property face property locale))) + (error "Property must have a specification in locale %S" locale)) + (map-specifier + sp + (lambda (sp locale inst-list func) + (let* ((device (dfw-device locale)) + ;; if a device can be derived from the locale, + ;; call frob-face-property-1 for that device. + ;; Otherwise map frob-face-property-1 over each device. + (result + (if device + (list (frob-face-property-1 sp device inst-list func)) + (mapcar (lambda (device) + (frob-face-property-1 sp device + inst-list func)) + (device-list)))) + new-result) + ;; remove duplicates and nils from the obtained list of + ;; instantiators. + (mapcar (lambda (arg) + (when (and arg (not (member arg new-result))) + (setq new-result (cons arg new-result)))) + result) + ;; add back in. + (add-spec-list-to-specifier sp (list (cons locale new-result))) + ;; tell map-specifier to keep going. + nil)) + locale + func)))) + +(defun frob-face-property-1 (sp device inst-list func) + (let + (first-valid result) + (while (and inst-list (not result)) + (let* ((inst-pair (car inst-list)) + (tag-set (car inst-pair)) + (sp-inst (specifier-instance-from-inst-list + sp device (list inst-pair)))) + (if sp-inst + (progn + (if (not first-valid) + (setq first-valid inst-pair)) + (setq result (funcall func sp-inst device)) + (if result + (setq result (cons tag-set result)))))) + (setq inst-list (cdr inst-list))) + (or result first-valid))) + +(defun frob-face-font-2 (face locale unfrobbed-face frobbed-face + tty-thunk x-thunk standard-face-mapping) + ;; another kludge to make things more intuitive. If we're + ;; inheriting from a standard face in this locale, frob the + ;; inheritance as appropriate. Else, if, after the first X frobbing + ;; pass, the face hasn't changed and still looks like the standard + ;; unfrobbed face (e.g. 'default), make it inherit from the standard + ;; frobbed face (e.g. 'bold). Regardless of things, do the TTY + ;; frobbing. + + ;; yuck -- The LOCALE argument to make-face-bold is not actually a locale, + ;; but is a "locale, locale-type, or nil for all". So ... do our extra + ;; frobbing only if it's actually a locale; or for nil, do the frobbing + ;; on 'global. This specifier stuff needs some rethinking. + (let* ((the-locale (cond ((null locale) 'global) + ((valid-specifier-locale-p locale) locale) + (t nil))) + (specs (and the-locale (face-font face the-locale nil t))) + (change-it (and specs (cdr (assoc specs standard-face-mapping))))) + (if (and change-it + (not (memq (face-name (find-face face)) + '(default bold italic bold-italic)))) + (progn + (or (equal change-it t) + (set-face-property face 'font change-it the-locale)) + (funcall tty-thunk)) + (let* ((domain (cond ((null the-locale) nil) + ((valid-specifier-domain-p the-locale) the-locale) + ;; OK, this next one is truly a kludge, but + ;; it results in more intuitive behavior most + ;; of the time. (really!) + ((or (eq the-locale 'global) (eq the-locale 'all)) + (selected-device)) + (t nil))) + (inst (and domain (face-property-instance face 'font domain)))) + (funcall tty-thunk) + (funcall x-thunk) + ;; If it's reasonable to do the inherit-from-standard-face trick, + ;; and it's called for, then do it now. + (or (null domain) + (not (equal inst (face-property-instance face 'font domain))) + ;; don't do it for standard faces, or you'll get inheritance loops. + ;; #### This makes XEmacs seg fault! fix this bug. + (memq (face-name (find-face face)) + '(default bold italic bold-italic)) + (not (equal (face-property-instance face 'font domain) + (face-property-instance unfrobbed-face 'font domain))) + (set-face-property face 'font (vector frobbed-face) + the-locale)))))) + +(defun make-face-bold (face &optional locale) + "Make the face bold, if possible. +This will attempt to make the font bold for X locales and will set the +highlight flag for TTY locales. + +If LOCALE is nil, omitted, or `all', this will attempt to frob all +font specifications for FACE to make them appear bold. Similarly, if +LOCALE is a locale type, this frobs all font specifications for locales +of that type. If LOCALE is a particular locale, what happens depends on +what sort of locale is given. If you gave a device, frame, or window, +then it's always possible to determine what the font actually will be, +so this is determined and the resulting font is frobbed and added back as a +specification for this locale. If LOCALE is a buffer, however, you can't +determine what the font will actually be unless there's actually a +specification given for that particular buffer (otherwise, it depends +on what window and frame the buffer appears in, and might not even be +well-defined if the buffer appears multiple times in different places); +therefore you will get an error unless there's a specification for the +buffer. + +Finally, in some cases (specifically, when LOCALE is not a locale type), +if the frobbing didn't actually make the font look any different +\(this happens, for example, if your font specification is already bold +or has no bold equivalent), and currently looks like the font of the +'default face, it is set to inherit from the 'bold face. This is kludgy +but it makes `make-face-bold' have more intuitive behavior in many +circumstances." + (interactive (list (read-face-name "Make which face bold: "))) + (frob-face-font-2 + face locale 'default 'bold + (lambda () + ;; handle TTY specific entries + (when (featurep 'tty) + (set-face-highlight-p face t locale 'tty))) + (lambda () + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-make-font-bold locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-make-font-bold locale)) + )) + '(([default] . [bold]) + ([bold] . t) + ([italic] . [bold-italic]) + ([bold-italic] . t)))) + +(defun make-face-italic (face &optional locale) + "Make the face italic, if possible. +This will attempt to make the font italic for X locales and will set +the underline flag for TTY locales. +See `make-face-bold' for the semantics of the LOCALE argument and +for more specifics on exactly how this function works." + (interactive (list (read-face-name "Make which face italic: "))) + (frob-face-font-2 + face locale 'default 'italic + (lambda () + ;; handle TTY specific entries + (when (featurep 'tty) + (set-face-underline-p face t locale 'tty))) + (lambda () + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-make-font-italic locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-make-font-italic locale)) + )) + '(([default] . [italic]) + ([bold] . [bold-italic]) + ([italic] . t) + ([bold-italic] . t)))) + +(defun make-face-bold-italic (face &optional locale) + "Make the face bold and italic, if possible. +This will attempt to make the font bold-italic for X locales and will +set the highlight and underline flags for TTY locales. +See `make-face-bold' for the semantics of the LOCALE argument and +for more specifics on exactly how this function works." + (interactive (list (read-face-name "Make which face bold-italic: "))) + (frob-face-font-2 + face locale 'default 'bold-italic + (lambda () + ;; handle TTY specific entries + (when (featurep 'tty) + (set-face-highlight-p face t locale 'tty) + (set-face-underline-p face t locale 'tty))) + (lambda () + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-make-font-bold-italic locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-make-font-bold-italic locale)) + )) + '(([default] . [italic]) + ([bold] . [bold-italic]) + ([italic] . [bold-italic]) + ([bold-italic] . t)))) + +(defun make-face-unbold (face &optional locale) + "Make the face non-bold, if possible. +This will attempt to make the font non-bold for X locales and will +unset the highlight flag for TTY locales. +See `make-face-bold' for the semantics of the LOCALE argument and +for more specifics on exactly how this function works." + (interactive (list (read-face-name "Make which face non-bold: "))) + (frob-face-font-2 + face locale 'bold 'default + (lambda () + ;; handle TTY specific entries + (when (featurep 'tty) + (set-face-highlight-p face nil locale 'tty))) + (lambda () + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-make-font-unbold locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-make-font-unbold locale)) + )) + '(([default] . t) + ([bold] . [default]) + ([italic] . t) + ([bold-italic] . [italic])))) + +(defun make-face-unitalic (face &optional locale) + "Make the face non-italic, if possible. +This will attempt to make the font non-italic for X locales and will +unset the underline flag for TTY locales. +See `make-face-bold' for the semantics of the LOCALE argument and +for more specifics on exactly how this function works." + (interactive (list (read-face-name "Make which face non-italic: "))) + (frob-face-font-2 + face locale 'italic 'default + (lambda () + ;; handle TTY specific entries + (when (featurep 'tty) + (set-face-underline-p face nil locale 'tty))) + (lambda () + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-make-font-unitalic locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-make-font-unitalic locale)) + )) + '(([default] . t) + ([bold] . t) + ([italic] . [default]) + ([bold-italic] . [bold])))) + + +;; Why do the following two functions lose so badly in so many +;; circumstances? + +(defun make-face-smaller (face &optional locale) + "Make the font of the given face be smaller, if possible. +LOCALE works as in `make-face-bold' et al., but the ``inheriting- +from-the-bold-face'' operations described there are not done +because they don't make sense in this context." + (interactive (list (read-face-name "Shrink which face: "))) + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-find-smaller-font locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-find-smaller-font locale)))) + +(defun make-face-larger (face &optional locale) + "Make the font of the given face be larger, if possible. +See `make-face-smaller' for the semantics of the LOCALE argument." + (interactive (list (read-face-name "Enlarge which face: "))) + ;; handle X specific entries + (cond ((featurep 'x) + (frob-face-property face 'font 'x-find-larger-font locale)) + ((featurep 'w32) + (frob-face-property face 'font 'w32-find-larger-font locale)))) + +(defun invert-face (face &optional locale) + "Swap the foreground and background colors of the face." + (interactive (list (read-face-name "Invert face: "))) + (if (valid-specifier-domain-p locale) + (let ((foreface (face-foreground-instance face locale))) + (set-face-foreground face (face-background-instance face locale) + locale) + (set-face-background face foreface locale)) + (let ((forespec (copy-specifier (face-foreground face) nil locale))) + (copy-specifier (face-background face) (face-foreground face) locale) + (copy-specifier forespec (face-background face) locale)))) + + +;;; Convenience functions + +(defun face-ascent (face &optional domain charset) + "Return the ascent of a face. +See `face-property-instance' for the semantics of the DOMAIN argument." + (font-ascent (face-font face) domain charset)) + +(defun face-descent (face &optional domain charset) + "Return the descent of a face. +See `face-property-instance' for the semantics of the DOMAIN argument." + (font-descent (face-font face) domain charset)) + +(defun face-width (face &optional domain charset) + "Return the width of a face. +See `face-property-instance' for the semantics of the DOMAIN argument." + (font-width (face-font face) domain charset)) + +(defun face-height (face &optional domain charset) + "Return the height of a face. +See `face-property-instance' for the semantics of the DOMAIN argument." + (+ (face-ascent face domain charset) (face-descent face domain charset))) + +(defun face-proportional-p (face &optional domain charset) + "Return whether FACE is proportional. +See `face-property-instance' for the semantics of the DOMAIN argument." + (font-proportional-p (face-font face) domain charset)) + + +;; Functions that used to be in cus-face.el, but logically go here. + +(defcustom frame-background-mode nil + "*The brightness of the background. +Set this to the symbol dark if your background color is dark, light if +your background is light, or nil (default) if you want Emacs to +examine the brightness for you." + :group 'faces + :type '(choice (choice-item dark) + (choice-item light) + (choice-item :tag "Auto" nil))) + +;; The old variable that many people still have in .emacs files. +(define-obsolete-variable-alias 'custom-background-mode + 'frame-background-mode) + +(defun get-frame-background-mode (frame) + "Detect background mode for FRAME." + (let* ((color-instance (face-background-instance 'default frame)) + (mode (condition-case nil + (if (< (apply '+ (color-instance-rgb-components + color-instance)) 65536) + 'dark 'light) + ;; Here, we get an error on a TTY. As we don't have + ;; a good way of detecting whether a TTY is light or + ;; dark, we'll guess it's dark. + (error 'dark)))) + (set-frame-property frame 'background-mode mode) + mode)) + +(defun extract-custom-frame-properties (frame) + "Return a plist with the frame properties of FRAME used by custom." + (list 'type (or (frame-property frame 'display-type) + (device-type (frame-device frame))) + 'class (device-class (frame-device frame)) + 'background (or frame-background-mode + (frame-property frame 'background-mode) + (get-frame-background-mode frame)))) + +(defcustom init-face-from-resources t + "If non nil, attempt to initialize faces from the resource database." + :group 'faces + :type 'boolean) + +;; Old name, used by custom. Also, FSFmacs name. +(defvaralias 'initialize-face-resources 'init-face-from-resources) + +(defun face-spec-set (face spec &optional frame) + "Set FACE's face attributes according to the first matching entry in SPEC. +If optional FRAME is non-nil, set it for that frame only. +If it is nil, then apply SPEC to each frame individually. +See `defface' for information about SPEC." + (if frame + (progn + (reset-face face frame) + (face-display-set face spec frame) + (init-face-from-resources face frame)) + (let ((frames (relevant-custom-frames))) + (reset-face face) + (face-display-set face spec) + (while frames + (face-display-set face spec (car frames)) + (pop frames)) + (init-face-from-resources face)))) + +(defun face-display-set (face spec &optional frame) + "Set FACE to the attributes to the first matching entry in SPEC. +Iff optional FRAME is non-nil, set it for that frame only. +See `defface' for information about SPEC." + (while spec + (let ((display (caar spec)) + (atts (cadar spec))) + (pop spec) + (when (face-spec-set-match-display display frame) + ;; Avoid creating frame local duplicates of the global face. + (unless (and frame (eq display (get face 'custom-face-display))) + (apply 'face-custom-attributes-set face frame atts)) + (unless frame + (put face 'custom-face-display display)) + (setq spec nil))))) + +(defvar default-custom-frame-properties nil + "The frame properties used for the global faces. +Frames not matching these propertiess should have frame local faces. +The value should be nil, if uninitialized, or a plist otherwise. +See `defface' for a list of valid keys and values for the plist.") + +(defun get-custom-frame-properties (&optional frame) + "Return a plist with the frame properties of FRAME used by custom. +If FRAME is nil, return the default frame properties." + (cond (frame + ;; Try to get from cache. + (let ((cache (frame-property frame 'custom-properties))) + (unless cache + ;; Oh well, get it then. + (setq cache (extract-custom-frame-properties frame)) + ;; and cache it... + (set-frame-property frame 'custom-properties cache)) + cache)) + (default-custom-frame-properties) + (t + (setq default-custom-frame-properties + (extract-custom-frame-properties (selected-frame)))))) + +(defun face-spec-set-match-display (display frame) + "Non-nil iff DISPLAY matches FRAME. +DISPLAY is part of a spec such as can be used in `defface'. +If FRAME is nil, the current FRAME is used." + (if (eq display t) + t + (let* ((props (get-custom-frame-properties frame)) + (type (plist-get props 'type)) + (class (plist-get props 'class)) + (background (plist-get props 'background)) + (match t) + (entries display) + entry req options) + (while (and entries match) + (setq entry (car entries) + entries (cdr entries) + req (car entry) + options (cdr entry) + match (case req + (type (memq type options)) + (class (memq class options)) + (background (memq background options)) + (t (warn "Unknown req `%S' with options `%S'" + req options) + nil)))) + match))) + +(defun relevant-custom-frames () + "List of frames whose custom properties differ from the default." + (let ((relevant nil) + (default (get-custom-frame-properties)) + (frames (frame-list)) + frame) + (while frames + (setq frame (car frames) + frames (cdr frames)) + (unless (equal default (get-custom-frame-properties frame)) + (push frame relevant))) + relevant)) + +(defun initialize-custom-faces (&optional frame) + "Initialize all custom faces for FRAME. +If FRAME is nil or omitted, initialize them for all frames." + (mapc (lambda (symbol) + (let ((spec (or (get symbol 'saved-face) + (get symbol 'face-defface-spec)))) + (when spec + ;; No need to init-face-from-resources -- code in + ;; `init-frame-faces' does it already. + (face-display-set symbol spec frame)))) + (face-list))) + +(defun custom-initialize-frame (frame) + "Initialize frame-local custom faces for FRAME if necessary." + (unless (equal (get-custom-frame-properties) + (get-custom-frame-properties frame)) + (initialize-custom-faces frame))) + + +(defun make-empty-face (name &optional doc-string temporary) + "Like `make-face', but doesn't query the resource database." + (let ((init-face-from-resources nil)) + (make-face name doc-string temporary))) + +(defun init-face-from-resources (face &optional locale) + "Initialize FACE from the resource database. +If LOCALE is specified, it should be a frame, device, or 'global, and +the face will be resourced over that locale. Otherwise, the face will +be resourced over all possible locales (i.e. all frames, all devices, +and 'global)." + (cond ((null init-face-from-resources) + ;; Do nothing. + ) + ((not locale) + ;; Global, set for all frames. + (progn + (init-face-from-resources face 'global) + (let ((devices (device-list))) + (while devices + (init-face-from-resources face (car devices)) + (setq devices (cdr devices)))) + (let ((frames (frame-list))) + (while frames + (init-face-from-resources face (car frames)) + (setq frames (cdr frames)))))) + (t + ;; Specific. + (let ((devtype (cond ((devicep locale) (device-type locale)) + ((framep locale) (frame-type locale)) + (t nil)))) + (cond ((or (and (not devtype) (featurep 'x)) (eq 'x devtype)) + (x-init-face-from-resources face locale)) + ((or (not devtype) (eq 'tty devtype)) + ;; Nothing to do for TTYs? + )))))) + +(defun init-device-faces (device) + ;; First, add any device-local face resources. + (when init-face-from-resources + (loop for face in (face-list) do + (init-face-from-resources face device)) + ;; Then do any device-specific initialization. + (cond ((eq 'x (device-type device)) + (x-init-device-faces device)) + ((eq 'w32 (device-type device)) + (w32-init-device-faces device)) + ;; Nothing to do for TTYs? + ) + (init-other-random-faces device))) + +(defun init-frame-faces (frame) + (when init-face-from-resources + ;; First, add any frame-local face resources. + (loop for face in (face-list) do + (init-face-from-resources face frame)) + ;; Then do any frame-specific initialization. + (cond ((eq 'x (frame-type frame)) + (x-init-frame-faces frame)) + ((eq 'w32 (frame-type frame)) + (w32-init-frame-faces frame)) + ;; Is there anything which should be done for TTY's? + ))) + +;; #### This is somewhat X-specific, and is called when the first +;; X device is created (even if there were TTY devices created +;; beforehand). The concept of resources has not been generalized +;; outside of X-specificness, so we have to live with this +;; breach of device-independence. + +(defun init-global-faces () + ;; Look for global face resources. + (loop for face in (face-list) do + (init-face-from-resources face 'global)) + ;; Further X frobbing. + (x-init-global-faces) + ;; for bold and the like, make the global specification be bold etc. + ;; if the user didn't already specify a value. These will also be + ;; frobbed further in init-other-random-faces. + (unless (face-font 'bold 'global) + (make-face-bold 'bold 'global)) + ;; + (unless (face-font 'italic 'global) + (make-face-italic 'italic 'global)) + ;; + (unless (face-font 'bold-italic 'global) + (make-face-bold-italic 'bold-italic 'global) + (unless (face-font 'bold-italic 'global) + (copy-face 'bold 'bold-italic) + (make-face-italic 'bold-italic))) + + (when (face-equal 'bold 'bold-italic) + (copy-face 'italic 'bold-italic) + (make-face-bold 'bold-italic)) + ;; + ;; Nothing more to be done for X or TTY's? + ) + + +;; These warnings are there for a reason. Just specify your fonts +;; correctly. Deal with it. Additionally, one can use +;; `log-warning-minimum-level' instead of this. +;(defvar inhibit-font-complaints nil +; "Whether to suppress complaints about incomplete sets of fonts.") + +(defun face-complain-about-font (face device) + (if (symbolp face) (setq face (symbol-name face))) +;; (if (not inhibit-font-complaints) + (display-warning + 'font + (let ((default-name (face-font-name 'default device))) + (format "%s: couldn't deduce %s %s version of the font +%S. + +Please specify X resources to make the %s face +visually distinguishable from the default face. +For example, you could add one of the following to $HOME/Emacs: + +Emacs.%s.attributeFont: -dt-*-medium-i-* +or +Emacs.%s.attributeForeground: hotpink\n" + invocation-name + (if (string-match "\\`[aeiouAEIOU]" face) "an" "a") + face + default-name + face + face + face + )))) + + +;; #### This is quite a mess. We should use the custom mechanism for +;; most of this stuff. Currently we don't do it, because Custom +;; doesn't use specifiers (yet.) FSF does it the Right Way. + +;; For instance, the definition of `bold' should be something like +;; (defface bold ((t (:bold t))) "Bold text.") -- and `:bold t' should +;; make sure that everything works properly. + +(defun init-other-random-faces (device) + "Initializes the colors and fonts of the bold, italic, bold-italic, +zmacs-region, list-mode-item-selected, highlight, primary-selection, +secondary-selection, and isearch faces when each device is created. If +you want to add code to do stuff like this, use the create-device-hook." + + ;; try to make 'bold look different from the default on this device. + ;; If that doesn't work at all, then issue a warning. + (unless (face-differs-from-default-p 'bold device) + (make-face-bold 'bold device) + (unless (face-differs-from-default-p 'bold device) + (make-face-unbold 'bold device) + (unless (face-differs-from-default-p 'bold device) + ;; the luser specified one of the bogus font names + (face-complain-about-font 'bold device)))) + + ;; Similar for italic. + ;; It's unreasonable to expect to be able to make a font italic all + ;; the time. For many languages, italic is an alien concept. + ;; Basically, because italic is not a globally meaningful concept, + ;; the use of the italic face should really be oboleted. + + ;; I disagree with above. In many languages, the concept of capital + ;; letters is just as alien, and yet we use them. Italic is here to + ;; stay. -hniksic + + ;; In a Solaris Japanese environment, there just aren't any italic + ;; fonts - period. CDE recognizes this reality, and fonts + ;; -dt-interface user-medium-r-normal-*-*-*-*-*-*-*-*-* don't come + ;; in italic versions. So we first try to make the font bold before + ;; complaining. + (unless (face-differs-from-default-p 'italic device) + (make-face-italic 'italic device) + (unless (face-differs-from-default-p 'italic device) + (make-face-bold 'italic device) + (unless (face-differs-from-default-p 'italic device) + (face-complain-about-font 'italic device)))) + + ;; similar for bold-italic. + (unless (face-differs-from-default-p 'bold-italic device) + (make-face-bold-italic 'bold-italic device) + ;; if we couldn't get a bold-italic version, try just bold. + (unless (face-differs-from-default-p 'bold-italic device) + (make-face-bold 'bold-italic device) + ;; if we couldn't get bold or bold-italic, then that's probably because + ;; the default font is bold, so make the `bold-italic' face be unbold. + (unless (face-differs-from-default-p 'bold-italic device) + (make-face-unbold 'bold-italic device) + (make-face-italic 'bold-italic device) + (unless (face-differs-from-default-p 'bold-italic device) + ;; if that didn't work, try plain italic + ;; (can this ever happen? what the hell.) + (make-face-italic 'bold-italic device) + (unless (face-differs-from-default-p 'bold-italic device) + ;; then bitch and moan. + (face-complain-about-font 'bold-italic device)))))) + + ;; Set the text-cursor colors unless already specified. + (when (and (not (eq 'tty (device-type device))) + (not (face-background 'text-cursor 'global)) + (face-property-equal 'text-cursor 'default 'background device)) + (set-face-background 'text-cursor [default foreground] 'global + nil 'append)) + (when (and (not (eq 'tty (device-type device))) + (not (face-foreground 'text-cursor 'global)) + (face-property-equal 'text-cursor 'default 'foreground device)) + (set-face-foreground 'text-cursor [default background] 'global + nil 'append)) + + ;; Set the secondary-selection color unless already specified. + (unless (or (face-differs-from-default-p 'highlight device) + (face-background 'highlight 'global)) + ;; some older servers don't recognize "darkseagreen2" + (set-face-background 'highlight + '((color . "darkseagreen2") + (color . "green")) + 'global nil 'append) + (set-face-background 'highlight "gray53" 'global 'grayscale 'append)) + (unless (or (face-differs-from-default-p 'highlight device) + (face-background-pixmap 'highlight 'global)) + (set-face-background-pixmap 'highlight [nothing] 'global 'color 'append) + (set-face-background-pixmap 'highlight [nothing] 'global 'grayscale 'append) + (set-face-background-pixmap 'highlight "gray1" 'global 'mono 'append)) + ;; if the highlight face isn't distinguished on this device, + ;; at least try inverting it. + (unless (face-differs-from-default-p 'highlight device) + (invert-face 'highlight device)) + + ;; first time through, set the zmacs-region color if it's not already + ;; specified. + (unless (or (face-differs-from-default-p 'zmacs-region device) + (face-background 'zmacs-region 'global)) + (set-face-background 'zmacs-region "gray65" 'global 'color) + (set-face-background 'zmacs-region "gray65" 'global 'grayscale)) + (unless (or (face-differs-from-default-p 'zmacs-region device) + (face-background-pixmap 'zmacs-region 'global)) + (set-face-background-pixmap 'zmacs-region [nothing] 'global 'color) + (set-face-background-pixmap 'zmacs-region [nothing] 'global 'grayscale) + (set-face-background-pixmap 'zmacs-region "gray3" 'global 'mono)) + ;; if the zmacs-region face isn't distinguished on this device, + ;; at least try inverting it. + (unless (face-differs-from-default-p 'zmacs-region device) + (invert-face 'zmacs-region device)) + + ;; first time through, set the list-mode-item-selected color if it's + ;; not already specified. + (unless (or (face-differs-from-default-p 'list-mode-item-selected device) + (face-background 'list-mode-item-selected 'global)) + (set-face-background 'list-mode-item-selected "gray68" 'global 'color) + (set-face-background 'list-mode-item-selected "gray68" 'global 'grayscale) + (if (featurep 'x) + (unless (face-foreground 'list-mode-item-selected 'global) + (set-face-background 'list-mode-item-selected + [default foreground] 'global '(mono x)) + (set-face-foreground 'list-mode-item-selected + [default background] 'global '(mono x))))) + + ;; if the list-mode-item-selected face isn't distinguished on this device, + ;; at least try inverting it. + (unless (face-differs-from-default-p 'list-mode-item-selected device) + (invert-face 'list-mode-item-selected device)) + + ;; Set the primary-selection color unless already specified. + (unless (or (face-differs-from-default-p 'primary-selection device) + (face-background 'primary-selection 'global)) + (set-face-background 'primary-selection "gray65" 'global 'color) + (set-face-background 'primary-selection "gray65" 'global 'grayscale)) + (unless (or (face-differs-from-default-p 'secondary-selection device) + (face-background-pixmap 'primary-selection 'global)) + (set-face-background-pixmap 'primary-selection "gray3" 'global 'mono)) + ;; If the primary-selection face isn't distinguished on this device, + ;; at least try inverting it. + (unless (face-differs-from-default-p 'primary-selection device) + (invert-face 'primary-selection device)) + + ;; Set the secondary-selection color unless already specified. + (unless (or (face-differs-from-default-p 'secondary-selection device) + (face-background 'secondary-selection 'global)) + (set-face-background 'secondary-selection + '((color . "paleturquoise") + (color . "green")) + 'global) + (set-face-background 'secondary-selection "gray53" 'global + 'grayscale)) + (unless (or (face-differs-from-default-p 'secondary-selection device) + (face-background-pixmap 'secondary-selection 'global)) + (set-face-background-pixmap 'secondary-selection "gray1" 'global 'mono)) + ;; If the secondary-selection face isn't distinguished on this device, + ;; at least try inverting it. + (unless (face-differs-from-default-p 'secondary-selection device) + (invert-face 'secondary-selection device)) + + ;; Set the isearch color if unless already specified. + (unless (or (face-differs-from-default-p 'isearch device) + (face-background 'isearch 'global)) + ;; TTY's and some older X servers don't recognize "paleturquoise" + (set-face-background 'isearch + '((color . "paleturquoise") + (color . "green")) + 'global)) + ;; if the isearch face isn't distinguished (e.g. we're not on a color + ;; display), at least try making it bold. + (unless (face-differs-from-default-p 'isearch device) + (set-face-font 'isearch [bold])) + ) + +;; New function with 20.1, suggested by Per Abrahamsen, coded by Kyle Jones. +(defun set-face-stipple (face pixmap &optional frame) + "Change the stipple pixmap of face FACE to PIXMAP. +This is an Emacs compatibility function; consider using +set-face-background-pixmap instead. + +PIXMAP should be a string, the name of a file of pixmap data. +The directories listed in the `x-bitmap-file-path' variable are searched. +Any kind of image file for which XEmacs has builtin support can be used. + +Alternatively, PIXMAP may be a list of the form (WIDTH HEIGHT +DATA) where WIDTH and HEIGHT are the size in pixels, and DATA is +a string, containing the raw bits of the bitmap. XBM data is +expected in this case, other types of image data will not work. + +If the optional FRAME argument is provided, change only +in that frame; otherwise change each frame." + (while (not (find-face face)) + (setq face (signal 'wrong-type-argument (list 'facep face)))) + (while (cond ((stringp pixmap) + (unless (file-readable-p pixmap) + (setq pixmap `[xbm :file ,pixmap])) + nil) + ((and (consp pixmap) (= (length pixmap) 3)) + (setq pixmap `[xbm :data ,pixmap]) + nil) + (t t)) + (setq pixmap (signal 'wrong-type-argument + (list 'stipple-pixmap-p pixmap)))) + (while (and frame (not (framep frame))) + (setq frame (signal 'wrong-type-argument (list 'framep frame)))) + (set-face-background-pixmap face pixmap frame)) + + +;; Create the remaining standard faces now. This way, packages that we dump +;; can reference these faces as parents. +;; +;; The default, modeline, left-margin, right-margin, text-cursor, +;; and pointer faces are created in C. + +(make-face 'bold "Bold text.") +(make-face 'italic "Italic text.") +(make-face 'bold-italic "Bold-italic text.") +(make-face 'underline "Underlined text.") +(or (face-differs-from-default-p 'underline) + (set-face-underline-p 'underline t 'global)) +(make-face 'zmacs-region "Used on highlightes region between point and mark.") +(make-face 'isearch "Used on region matched by isearch.") +(make-face 'list-mode-item-selected + "Face for the selected list item in list-mode.") +(make-face 'highlight "Highlight face.") +(make-face 'primary-selection "Primary selection face.") +(make-face 'secondary-selection "Secondary selection face.") + +;; Several useful color faces. +(eval-when-compile (load "cl-macs")) +(dolist (color '(red green blue yellow)) + (make-face color (concat (symbol-name color) " text.")) + (set-face-foreground color (symbol-name color) nil 'color)) + +;; Make some useful faces. This happens very early, before creating +;; the first non-stream device. We initialize the tty global values here. +;; We cannot initialize the X global values here because they depend +;; on having already resourced the global face specs, which happens +;; when the first X device is created. + +(set-face-background-pixmap 'modeline [nothing]) + +(when (featurep 'tty) + (set-face-highlight-p 'bold t 'global 'tty) + (set-face-underline-p 'italic t 'global 'tty) + (set-face-highlight-p 'bold-italic t 'global 'tty) + (set-face-underline-p 'bold-italic t 'global 'tty) + (set-face-highlight-p 'highlight t 'global 'tty) + (set-face-reverse-p 'text-cursor t 'global 'tty) + (set-face-reverse-p 'modeline t 'global 'tty) + (set-face-reverse-p 'zmacs-region t 'global 'tty) + (set-face-reverse-p 'primary-selection t 'global 'tty) + (set-face-underline-p 'secondary-selection t 'global 'tty) + (set-face-reverse-p 'list-mode-item-selected t 'global 'tty) + (set-face-reverse-p 'isearch t 'global 'tty) + ) + +;;; faces.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/files-nomule.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/files-nomule.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,96 @@ +;;; files-nomule.el --- file I/O stubs when not under Mule. + +;; Copyright (C) 1985-1987, 1992-1994, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995 Sun Microsystems. + +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.34 (files.el). (Is it? Please check) + +;;; Commentary: + +;; This file is dumped with XEmacs (when Mule is not compiled in). + +;; These stubs were moved from the bottom of files.el. + +;;; Code: + +(defun insert-file-contents (filename &optional visit beg end replace) + "Insert contents of file FILENAME after point. +Returns list of absolute file name and length of data inserted. +If second argument VISIT is non-nil, the buffer's visited filename +and last save file modtime are set, and it is marked unmodified. +If visiting and the file does not exist, visiting is completed +before the error is signaled. + +The optional third and fourth arguments BEG and END +specify what portion of the file to insert. +If VISIT is non-nil, BEG and END must be nil. +If optional fifth argument REPLACE is non-nil, +it means replace the current buffer contents (in the accessible portion) +with the file contents. This is better than simply deleting and inserting +the whole thing because (1) it preserves some marker positions +and (2) it puts less data in the undo list." + (insert-file-contents-internal filename visit beg end replace nil nil)) + +(defun write-region (start end filename &optional append visit lockname coding-system) + "Write current region into specified file. +By default, the file's existing contents are replaced by the specified region. +When called from a program, takes three arguments: +START, END and FILENAME. START and END are buffer positions. +Optional fourth argument APPEND if non-nil means + append to existing file contents (if any). +Optional fifth argument VISIT if t means + set the last-save-file-modtime of buffer to this file's modtime + and mark buffer not modified. +If VISIT is a string, it is a second file name; + the output goes to FILENAME, but the buffer is marked as visiting VISIT. + VISIT is also the file name to lock and unlock for clash detection. +If VISIT is neither t nor nil nor a string, + that means do not print the \"Wrote file\" message. +The optional sixth arg LOCKNAME, if non-nil, specifies the name to + use for locking and unlocking, overriding FILENAME and VISIT. +Kludgy feature: if START is a string, then that string is written +to the file, instead of any buffer contents, and END is ignored. +Optional seventh argument CODING-SYSTEM is meaningful only if support + for Mule is present in XEmacs and specifies the coding system + used to encode the text when it is written out, and defaults to + the value of `buffer-file-coding-system' in the current buffer. + When Mule support is not present, the CODING-SYSTEM argument is + ignored." + (interactive "r\nFWrite region to file: ") + (write-region-internal start end filename append visit lockname nil)) + +(defun load (file &optional noerror nomessage nosuffix) + "Execute a file of Lisp code named FILE. +First try FILE with `.elc' appended, then try with `.el', + then try FILE unmodified. +This function searches the directories in `load-path'. +If optional second arg NOERROR is non-nil, + report no error if FILE doesn't exist. +Print messages at start and end of loading unless + optional third arg NOMESSAGE is non-nil (ignored in -batch mode). +If optional fourth arg NOSUFFIX is non-nil, don't try adding + suffixes `.elc' or `.el' to the specified name FILE. +Return t if file exists." + (load-internal file noerror nomessage nosuffix nil nil)) + +;;; files-nomule.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/files.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/files.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,3101 @@ +;;; files.el --- file input and output commands for XEmacs. + +;; Copyright (C) 1985-1987, 1992-1995, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995 Sun Microsystems. + +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34 [Partial]. +;;; Warning: Merging this file is tough. Beware. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; Defines most of XEmacs's file- and directory-handling functions, +;; including basic file visiting, backup generation, link handling, +;; ITS-id version control, load- and write-hook handling, and the like. + +;;; Code: + +;; XEmacs: Avoid compilation warnings. +(defvar coding-system-for-read) +(defvar buffer-file-coding-system) + +(defgroup backup nil + "Backups of edited data files." + :group 'files) + +(defgroup find-file nil + "Finding and editing files." + :group 'files) + + +;; XEmacs: In buffer.c +;(defconst delete-auto-save-files t +; "*Non-nil means delete auto-save file when a buffer is saved or killed.") + +;; FSF has automount-dir-prefix. Our directory-abbrev-alist is more general. +;; note: tmp_mnt bogosity conversion is established in paths.el. +(defcustom directory-abbrev-alist nil + "*Alist of abbreviations for file directories. +A list of elements of the form (FROM . TO), each meaning to replace +FROM with TO when it appears in a directory name. +This replacement is done when setting up the default directory of a +newly visited file. *Every* FROM string should start with \\\\` or ^. + +Use this feature when you have directories which you normally refer to +via absolute symbolic links or to eliminate automounter mount points +from the beginning of your filenames. Make TO the name of the link, +and FROM the name it is linked to." + :type '(repeat (cons :format "%v" + :value ("\\`" . "") + (regexp :tag "From") + (regexp :tag "To"))) + :group 'find-file) + +;;; Turn off backup files on VMS since it has version numbers. +(defcustom make-backup-files (not (eq system-type 'vax-vms)) + "*Non-nil means make a backup of a file the first time it is saved. +This can be done by renaming the file or by copying. + +Renaming means that XEmacs renames the existing file so that it is a +backup file, then writes the buffer into a new file. Any other names +that the old file had will now refer to the backup file. The new file +is owned by you and its group is defaulted. + +Copying means that XEmacs copies the existing file into the backup +file, then writes the buffer on top of the existing file. Any other +names that the old file had will now refer to the new (edited) file. +The file's owner and group are unchanged. + +The choice of renaming or copying is controlled by the variables +`backup-by-copying', `backup-by-copying-when-linked' and +`backup-by-copying-when-mismatch'. See also `backup-inhibited'." + :type 'boolean + :group 'backup) + +;; Do this so that local variables based on the file name +;; are not overridden by the major mode. +(defvar backup-inhibited nil + "Non-nil means don't make a backup, regardless of the other parameters. +This variable is intended for use by making it local to a buffer. +But it is local only if you make it local.") +(put 'backup-inhibited 'permanent-local t) + +(defcustom backup-by-copying nil + "*Non-nil means always use copying to create backup files. +See documentation of variable `make-backup-files'." + :type 'boolean + :group 'backup) + +(defcustom backup-by-copying-when-linked nil + "*Non-nil means use copying to create backups for files with multiple names. +This causes the alternate names to refer to the latest version as edited. +This variable is relevant only if `backup-by-copying' is nil." + :type 'boolean + :group 'backup) + +(defcustom backup-by-copying-when-mismatch nil + "*Non-nil means create backups by copying if this preserves owner or group. +Renaming may still be used (subject to control of other variables) +when it would not result in changing the owner or group of the file; +that is, for files which are owned by you and whose group matches +the default for a new file created there by you. +This variable is relevant only if `backup-by-copying' is nil." + :type 'boolean + :group 'backup) + +(defvar backup-enable-predicate + '(lambda (name) + (or (< (length name) 5) + (not (string-equal "/tmp/" (substring name 0 5))))) + "Predicate that looks at a file name and decides whether to make backups. +Called with an absolute file name as argument, it returns t to enable backup.") + +(defcustom buffer-offer-save nil + "*Non-nil in a buffer means offer to save the buffer on exit +even if the buffer is not visiting a file. +Automatically local in all buffers." + :type 'boolean + :group 'find-file) +(make-variable-buffer-local 'buffer-offer-save) + +;; FSF uses normal defconst +(defvaralias 'find-file-visit-truename 'find-file-use-truenames) +(defvaralias 'find-file-existing-other-name 'find-file-compare-truenames) + +(defcustom revert-without-query nil + "*Specify which files should be reverted without query. +The value is a list of regular expressions. +If the file name matches one of these regular expressions, +then `revert-buffer' reverts the file without querying +if the file has changed on disk and you have not edited the buffer." + :type '(repeat (regexp "")) + :group 'find-file) + +(defvar buffer-file-number nil + "The device number and file number of the file visited in the current buffer. +The value is a list of the form (FILENUM DEVNUM). +This pair of numbers uniquely identifies the file. +If the buffer is visiting a new file, the value is nil.") +(make-variable-buffer-local 'buffer-file-number) +(put 'buffer-file-number 'permanent-local t) + +(defvar buffer-file-numbers-unique (not (memq system-type '(windows-nt))) + "Non-nil means that buffer-file-number uniquely identifies files.") + +(defcustom file-precious-flag nil + "*Non-nil means protect against I/O errors while saving files. +Some modes set this non-nil in particular buffers. + +This feature works by writing the new contents into a temporary file +and then renaming the temporary file to replace the original. +In this way, any I/O error in writing leaves the original untouched, +and there is never any instant where the file is nonexistent. + +Note that this feature forces backups to be made by copying. +Yet, at the same time, saving a precious file +breaks any hard links between it and other files." + :type 'boolean + :group 'backup) + +(defcustom version-control nil + "*Control use of version numbers for backup files. +t means make numeric backup versions unconditionally. +nil means make them for files that have some already. +`never' means do not make them." + :type 'boolean + :group 'backup + :group 'vc) + +;; This is now defined in efs. +;(defvar dired-kept-versions 2 +; "*When cleaning directory, number of versions to keep.") + +(defcustom delete-old-versions nil + "*If t, delete excess backup versions silently. +If nil, ask confirmation. Any other value prevents any trimming." + :type '(choice (const :tag "Delete" t) + (const :tag "Ask" nil) + (sexp :tag "Leave" :format "%t\n" other)) + :group 'backup) + +(defcustom kept-old-versions 2 + "*Number of oldest versions to keep when a new numbered backup is made." + :type 'integer + :group 'backup) + +(defcustom kept-new-versions 2 + "*Number of newest versions to keep when a new numbered backup is made. +Includes the new backup. Must be > 0" + :type 'integer + :group 'backup) + +(defcustom require-final-newline nil + "*Value of t says silently ensure a file ends in a newline when it is saved. +Non-nil but not t says ask user whether to add a newline when there isn't one. +nil means don't add newlines." + :type '(choice (const :tag "Off" nil) + (const :tag "Add" t) + (sexp :tag "Ask" :format "%t\n" ask)) + :group 'editing-basics) + +(defcustom auto-save-default t + "*Non-nil says by default do auto-saving of every file-visiting buffer." + :type 'boolean + :group 'auto-save) + +(defcustom auto-save-visited-file-name nil + "*Non-nil says auto-save a buffer in the file it is visiting, when practical. +Normally auto-save files are written under other names." + :type 'boolean + :group 'auto-save) + +(defcustom save-abbrevs nil + "*Non-nil means save word abbrevs too when files are saved. +Loading an abbrev file sets this to t." + :type 'boolean + :group 'abbrev) + +(defcustom find-file-run-dired t + "*Non-nil says run dired if `find-file' is given the name of a directory." + :type 'boolean + :group 'find-file) + +;;;It is not useful to make this a local variable. +;;;(put 'find-file-not-found-hooks 'permanent-local t) +(defvar find-file-not-found-hooks nil + "List of functions to be called for `find-file' on nonexistent file. +These functions are called as soon as the error is detected. +`buffer-file-name' is already set up. +The functions are called in the order given until one of them returns non-nil.") + +;;;It is not useful to make this a local variable. +;;;(put 'find-file-hooks 'permanent-local t) +(defvar find-file-hooks nil + "List of functions to be called after a buffer is loaded from a file. +The buffer's local variables (if any) will have been processed before the +functions are called.") + +(defvar write-file-hooks nil + "List of functions to be called before writing out a buffer to a file. +If one of them returns non-nil, the file is considered already written +and the rest are not called. +These hooks are considered to pertain to the visited file. +So this list is cleared if you change the visited file name. +See also `write-contents-hooks' and `continue-save-buffer'.") +;;; However, in case someone does make it local... +(put 'write-file-hooks 'permanent-local t) + +(defvar local-write-file-hooks nil + "Just like `write-file-hooks', except intended for per-buffer use. +The functions in this list are called before the ones in +`write-file-hooks'. + +This variable is meant to be used for hooks that have to do with a +particular visited file. Therefore, it is a permanent local, so that +changing the major mode does not clear it. However, calling +`set-visited-file-name' does clear it.") +(make-variable-buffer-local 'local-write-file-hooks) +(put 'local-write-file-hooks 'permanent-local t) + + +;; #### think about this (added by Sun). +(put 'after-set-visited-file-name-hooks 'permanent-local t) +(defvar after-set-visited-file-name-hooks nil + "List of functions to be called after \\[set-visited-file-name] +or during \\[write-file]. +You can use this hook to restore local values of write-file-hooks, +after-save-hook, and revert-buffer-function, which pertain +to a specific file and therefore are normally killed by a rename. +Put hooks pertaining to the buffer contents on write-contents-hooks +and revert-buffer-insert-file-contents-function.") + +(defvar write-contents-hooks nil + "List of functions to be called before writing out a buffer to a file. +If one of them returns non-nil, the file is considered already written +and the rest are not called. +These hooks are considered to pertain to the buffer's contents, +not to the particular visited file; thus, `set-visited-file-name' does +not clear this variable, but changing the major mode does clear it. +See also `write-file-hooks' and `continue-save-buffer'.") + +;; XEmacs addition +;; Energize needed this to hook into save-buffer at a lower level; we need +;; to provide a new output method, but don't want to have to duplicate all +;; of the backup file and file modes logic.that does not occur if one uses +;; a write-file-hook which returns non-nil. +(put 'write-file-data-hooks 'permanent-local t) +(defvar write-file-data-hooks nil + "List of functions to be called to put the bytes on disk. +These functions receive the name of the file to write to as argument. +The default behavior is to call + (write-region (point-min) (point-max) filename nil t) +If one of them returns non-nil, the file is considered already written +and the rest are not called. +These hooks are considered to pertain to the visited file. +So this list is cleared if you change the visited file name. +See also `write-file-hooks'.") + +(defcustom enable-local-variables t + "*Control use of local-variables lists in files you visit. +The value can be t, nil or something else. +A value of t means local-variables lists are obeyed; +nil means they are ignored; anything else means query. + +The command \\[normal-mode] always obeys local-variables lists +and ignores this variable." + :type '(choice (const :tag "Obey" t) + (const :tag "Ignore" nil) + (sexp :tag "Query" :format "%t\n" other)) + :group 'find-file) + +(defcustom enable-local-eval 'maybe + "*Control processing of the \"variable\" `eval' in a file's local variables. +The value can be t, nil or something else. +A value of t means obey `eval' variables; +nil means ignore them; anything else means query. + +The command \\[normal-mode] always obeys local-variables lists +and ignores this variable." + :type '(choice (const :tag "Obey" t) + (const :tag "Ignore" nil) + (sexp :tag "Query" :format "%t\n" other)) + :group 'find-file) + +;; Avoid losing in versions where CLASH_DETECTION is disabled. +(or (fboundp 'lock-buffer) + (defalias 'lock-buffer 'ignore)) +(or (fboundp 'unlock-buffer) + (defalias 'unlock-buffer 'ignore)) + +;;FSFmacs bastardized ange-ftp cruft +;; This hook function provides support for ange-ftp host name +;; completion. It runs the usual ange-ftp hook, but only for +;; completion operations. Having this here avoids the need +;; to load ange-ftp when it's not really in use. +;(defun ange-ftp-completion-hook-function (op &rest args) +; (if (memq op '(file-name-completion file-name-all-completions)) +; (apply 'ange-ftp-hook-function op args) +; (let ((inhibit-file-name-handlers +; (cons 'ange-ftp-completion-hook-function +; (and (eq inhibit-file-name-operation op) +; inhibit-file-name-handlers))) +; (inhibit-file-name-operation op)) +; (apply op args)) + +(defun convert-standard-filename (filename) + "Convert a standard file's name to something suitable for the current OS. +This function's standard definition is trivial; it just returns the argument. +However, on some systems, the function is redefined +with a definition that really does change some file names." + filename) + +(defun pwd () + "Show the current default directory." + (interactive nil) + (message "Directory %s" default-directory)) + +(defvar cd-path nil + "Value of the CDPATH environment variable, as a list. +Not actually set up until the first time you use it.") + +(defvar path-separator ":" + "Character used to separate concatenated paths.") + +(defun parse-colon-path (cd-path) + "Explode a colon-separated list of paths into a string list." + (and cd-path + (let (cd-list (cd-start 0) cd-colon) + (setq cd-path (concat cd-path path-separator)) + (while (setq cd-colon (string-match path-separator cd-path cd-start)) + (setq cd-list + (nconc cd-list + (list (if (= cd-start cd-colon) + nil + (substitute-in-file-name + (file-name-as-directory + (substring cd-path cd-start cd-colon))))))) + (setq cd-start (+ cd-colon 1))) + cd-list))) + +(defun cd-absolute (dir) + "Change current directory to given absolute file name DIR." + ;; Put the name into directory syntax now, + ;; because otherwise expand-file-name may give some bad results. + (if (not (eq system-type 'vax-vms)) + (setq dir (file-name-as-directory dir))) + ;; XEmacs change: stig@hackvan.com + (if find-file-use-truenames + (setq dir (file-truename dir))) + (setq dir (abbreviate-file-name (expand-file-name dir))) + (cond ((not (file-directory-p dir)) + (error "%s is not a directory" dir)) + ;; this breaks ange-ftp, which doesn't (can't?) overload `file-executable-p'. + ;;((not (file-executable-p dir)) + ;; (error "Cannot cd to %s: Permission denied" dir)) + (t + (setq default-directory dir)))) + +(defun cd (dir) + "Make DIR become the current buffer's default directory. +If your environment includes a `CDPATH' variable, try each one of that +colon-separated list of directories when resolving a relative directory name." + (interactive + ;; XEmacs change? (read-file-name => read-directory-name) + (list (read-directory-name "Change default directory: " + default-directory default-directory + (and (member cd-path '(nil ("./"))) + (null (getenv "CDPATH")))))) + (if (file-name-absolute-p dir) + (cd-absolute (expand-file-name dir)) + ;; XEmacs + (if (null cd-path) + ;;#### Unix-specific + (let ((trypath (parse-colon-path (getenv "CDPATH")))) + (setq cd-path (or trypath (list "./"))))) + (or (catch 'found + (mapcar #'(lambda (x) + (let ((f (expand-file-name (concat x dir)))) + (if (file-directory-p f) + (progn + (cd-absolute f) + (throw 'found t))))) + cd-path) + nil) + ;; jwz: give a better error message to those of us with the + ;; good taste not to use a kludge like $CDPATH. + (if (equal cd-path '("./")) + (error "No such directory: %s" (expand-file-name dir)) + (error "Directory not found in $CDPATH: %s" dir))))) + +(defun load-file (file) + "Load the Lisp file named FILE." + (interactive "fLoad file: ") + (load (expand-file-name file) nil nil t)) + +; We now dump utils/lib-complete.el which has improved versions of this. +;(defun load-library (library) +; "Load the library named LIBRARY. +;This is an interface to the function `load'." +; (interactive "sLoad library: ") +; (load library)) +; +;(defun find-library (library) +; "Find the library of Lisp code named LIBRARY. +;This searches `load-path' for a file named either \"LIBRARY\" or \"LIBRARY.el\"." +; (interactive "sFind library file: ") +; (let ((f (locate-file library load-path ":.el:"))) +; (if f +; (find-file f) +; (error "Couldn't locate library %s" library)))) + +(defun file-local-copy (file &optional buffer) + "Copy the file FILE into a temporary file on this machine. +Returns the name of the local copy, or nil, if FILE is directly +accessible." + (let ((handler (find-file-name-handler file 'file-local-copy))) + (if handler + (funcall handler 'file-local-copy file) + nil))) + +;; XEmacs change block +; We have this in C and use the realpath() system call. + +;(defun file-truename (filename &optional counter prev-dirs) +; "Return the truename of FILENAME, which should be absolute. +;The truename of a file name is found by chasing symbolic links +;both at the level of the file and at the level of the directories +;containing it, until no links are left at any level. +; +;The arguments COUNTER and PREV-DIRS are used only in recursive calls. +;Do not specify them in other calls." +; ;; COUNTER can be a cons cell whose car is the count of how many more links +; ;; to chase before getting an error. +; ;; PREV-DIRS can be a cons cell whose car is an alist +; ;; of truenames we've just recently computed. +; ;; The last test looks dubious, maybe `+' is meant here? --simon. +; (if (or (string= filename "") (string= filename "~") +; (and (string= (substring filename 0 1) "~") +; (string-match "~[^/]*" filename))) +; (progn +; (setq filename (expand-file-name filename)) +; (if (string= filename "") +; (setq filename "/")))) +; (or counter (setq counter (list 100))) +; (let (done +; ;; For speed, remove the ange-ftp completion handler from the list. +; ;; We know it's not needed here. +; ;; For even more speed, do this only on the outermost call. +; (file-name-handler-alist +; (if prev-dirs file-name-handler-alist +; (let ((tem (copy-sequence file-name-handler-alist))) +; (delq (rassq 'ange-ftp-completion-hook-function tem) tem))))) +; (or prev-dirs (setq prev-dirs (list nil))) +; ;; If this file directly leads to a link, process that iteratively +; ;; so that we don't use lots of stack. +; (while (not done) +; (setcar counter (1- (car counter))) +; (if (< (car counter) 0) +; (error "Apparent cycle of symbolic links for %s" filename)) +; (let ((handler (find-file-name-handler filename 'file-truename))) +; ;; For file name that has a special handler, call handler. +; ;; This is so that ange-ftp can save time by doing a no-op. +; (if handler +; (setq filename (funcall handler 'file-truename filename) +; done t) +; (let ((dir (or (file-name-directory filename) default-directory)) +; target dirfile) +; ;; Get the truename of the directory. +; (setq dirfile (directory-file-name dir)) +; ;; If these are equal, we have the (or a) root directory. +; (or (string= dir dirfile) +; ;; If this is the same dir we last got the truename for, +; ;; save time--don't recalculate. +; (if (assoc dir (car prev-dirs)) +; (setq dir (cdr (assoc dir (car prev-dirs)))) +; (let ((old dir) +; (new (file-name-as-directory (file-truename dirfile counter prev-dirs)))) +; (setcar prev-dirs (cons (cons old new) (car prev-dirs))) +; (setq dir new)))) +; (if (equal ".." (file-name-nondirectory filename)) +; (setq filename +; (directory-file-name (file-name-directory (directory-file-name dir))) +; done t) +; (if (equal "." (file-name-nondirectory filename)) +; (setq filename (directory-file-name dir) +; done t) +; ;; Put it back on the file name. +; (setq filename (concat dir (file-name-nondirectory filename))) +; ;; Is the file name the name of a link? +; (setq target (file-symlink-p filename)) +; (if target +; ;; Yes => chase that link, then start all over +; ;; since the link may point to a directory name that uses links. +; ;; We can't safely use expand-file-name here +; ;; since target might look like foo/../bar where foo +; ;; is itself a link. Instead, we handle . and .. above. +; (setq filename +; (if (file-name-absolute-p target) +; target +; (concat dir target)) +; done nil) +; ;; No, we are done! +; (setq done t)))))))) +; filename)) + +;; XEmacs addition. Called from `insert-file-contents-internal' +;; at the appropriate time. +(defun compute-buffer-file-truename (&optional buffer) + "Recomputes BUFFER's value of `buffer-file-truename' +based on the current value of `buffer-file-name'. +BUFFER defaults to the current buffer if unspecified." + (save-excursion + (set-buffer (or buffer (current-buffer))) + (cond ((null buffer-file-name) + (setq buffer-file-truename nil)) + ((setq buffer-file-truename (file-truename buffer-file-name)) + ;; it exists, we're done. + nil) + (t + ;; the file doesn't exist, but maybe the directory does. + (let* ((dir (file-name-directory buffer-file-name)) + (truedir (file-truename dir))) + (if truedir (setq dir truedir)) + (setq buffer-file-truename + (expand-file-name (file-name-nondirectory buffer-file-name) + dir))))) + (if (and find-file-use-truenames buffer-file-truename) + (setq buffer-file-name (abbreviate-file-name buffer-file-truename) + default-directory (file-name-directory buffer-file-name))) + buffer-file-truename)) +;; End XEmacs change block + +(defun file-chase-links (filename) + "Chase links in FILENAME until a name that is not a link. +Does not examine containing directories for links, +unlike `file-truename'." + (let (tem (count 100) (newname filename)) + (while (setq tem (file-symlink-p newname)) + (if (= count 0) + (error "Apparent cycle of symbolic links for %s" filename)) + ;; In the context of a link, `//' doesn't mean what XEmacs thinks. + (while (string-match "//+" tem) + (setq tem (concat (substring tem 0 (1+ (match-beginning 0))) + (substring tem (match-end 0))))) + ;; Handle `..' by hand, since it needs to work in the + ;; target of any directory symlink. + ;; This code is not quite complete; it does not handle + ;; embedded .. in some cases such as ./../foo and foo/bar/../../../lose. + (while (string-match "\\`\\.\\./" tem) ;#### Unix specific + (setq tem (substring tem 3)) + (setq newname (file-name-as-directory + ;; Do the .. by hand. + (directory-file-name + (file-name-directory + ;; Chase links in the default dir of the symlink. + (file-chase-links + (directory-file-name + (file-name-directory newname)))))))) + (setq newname (expand-file-name tem (file-name-directory newname))) + (setq count (1- count))) + newname)) + +(defun switch-to-other-buffer (arg) + "Switch to the previous buffer. With a numeric arg, n, switch to the nth +most recent buffer. With an arg of 0, buries the current buffer at the +bottom of the buffer stack." + (interactive "p") + (if (eq arg 0) + (bury-buffer (current-buffer))) + (switch-to-buffer + (if (<= arg 1) (other-buffer (current-buffer)) + (nth (1+ arg) (buffer-list))))) + +(defun switch-to-buffer-other-window (buffer) + "Select buffer BUFFER in another window." + (interactive "BSwitch to buffer in other window: ") + (let ((pop-up-windows t)) + ;; XEmacs: this used to have (selected-frame) as the third argument, + ;; but this is obnoxious. If the user wants the buffer in a + ;; different frame, then it should be this way. + + ;; Change documented above undone --mrb + (pop-to-buffer buffer t (selected-frame)))) + +(defun switch-to-buffer-other-frame (buffer) + "Switch to buffer BUFFER in a newly-created frame." + (interactive "BSwitch to buffer in other frame: ") + (let* ((name (get-frame-name-for-buffer buffer)) + (frame (make-frame (if name + (list (cons 'name (symbol-name name))))))) + (pop-to-buffer buffer t frame) + (make-frame-visible frame) + buffer)) + +(defun find-file (filename &optional codesys) + "Edit file FILENAME. +Switch to a buffer visiting file FILENAME, +creating one if none already exists. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "FFind file: \nZCoding system: ") + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (switch-to-buffer (find-file-noselect filename))) + (switch-to-buffer (find-file-noselect filename)))) + +(defun find-file-other-window (filename &optional codesys) + "Edit file FILENAME, in another window. +May create a new window, or reuse an existing one. +See the function `display-buffer'. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "FFind file in other window: \nZCoding system: ") + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (switch-to-buffer-other-window (find-file-noselect filename))) + (switch-to-buffer-other-window (find-file-noselect filename)))) + +(defun find-file-other-frame (filename &optional codesys) + "Edit file FILENAME, in a newly-created frame. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "FFind file in other frame: \nZCoding system: ") + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (switch-to-buffer-other-frame (find-file-noselect filename))) + (switch-to-buffer-other-frame (find-file-noselect filename)))) + +(defun find-file-read-only (filename &optional codesys) + "Edit file FILENAME but don't allow changes. +Like \\[find-file] but marks buffer as read-only. +Use \\[toggle-read-only] to permit editing. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "fFind file read-only: \nZCoding system: ") + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (find-file filename)) + (find-file filename)) + (setq buffer-read-only t) + (current-buffer)) + +(defun find-file-read-only-other-window (filename &optional codesys) + "Edit file FILENAME in another window but don't allow changes. +Like \\[find-file-other-window] but marks buffer as read-only. +Use \\[toggle-read-only] to permit editing. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "fFind file read-only other window: \nZCoding system: ") + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (find-file-other-window filename)) + (find-file-other-window filename)) + (setq buffer-read-only t) + (current-buffer)) + +(defun find-file-read-only-other-frame (filename &optional codesys) + "Edit file FILENAME in another frame but don't allow changes. +Like \\[find-file-other-frame] but marks buffer as read-only. +Use \\[toggle-read-only] to permit editing. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "fFind file read-only other frame: \nZCoding system: ") + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (find-file-other-frame filename)) + (find-file-other-frame filename)) + (setq buffer-read-only t) + (current-buffer)) + +(defun find-alternate-file-other-window (filename &optional codesys) + "Find file FILENAME as a replacement for the file in the next window. +This command does not select that window. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive + (save-selected-window + (other-window 1) + (let ((file buffer-file-name) + (file-name nil) + (file-dir nil)) + (and file + (setq file-name (file-name-nondirectory file) + file-dir (file-name-directory file))) + (list (read-file-name + "Find alternate file: " file-dir nil nil file-name) + (if (and current-prefix-arg (featurep 'mule)) + (read-coding-system "Coding-system: ")))))) + (if (one-window-p) + (find-file-other-window filename) + (save-selected-window + (other-window 1) + (find-alternate-file filename codesys)))) + +(defun find-alternate-file (filename &optional codesys) + "Find file FILENAME, select its buffer, kill previous buffer. +If the current buffer now contains an empty file that you just visited +\(presumably by mistake), use this command to visit the file you really want. +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive + (let ((file buffer-file-name) + (file-name nil) + (file-dir nil)) + (and file + (setq file-name (file-name-nondirectory file) + file-dir (file-name-directory file))) + (list (read-file-name + "Find alternate file: " file-dir nil nil file-name) + (if (and current-prefix-arg (featurep 'mule)) + (read-coding-system "Coding-system: "))))) + (and (buffer-modified-p) (buffer-file-name) + ;; (not buffer-read-only) + (not (yes-or-no-p (format + "Buffer %s is modified; kill anyway? " + (buffer-name)))) + (error "Aborted")) + (let ((obuf (current-buffer)) + (ofile buffer-file-name) + (onum buffer-file-number) + (otrue buffer-file-truename) + (oname (buffer-name))) + (if (get-buffer " **lose**") + (kill-buffer " **lose**")) + (rename-buffer " **lose**") + (setq buffer-file-name nil) + (setq buffer-file-number nil) + (setq buffer-file-truename nil) + (unwind-protect + (progn + (unlock-buffer) + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (find-file filename)) + (find-file filename))) + (cond ((eq obuf (current-buffer)) + (setq buffer-file-name ofile) + (setq buffer-file-number onum) + (setq buffer-file-truename otrue) + (lock-buffer) + (rename-buffer oname)))) + (or (eq (current-buffer) obuf) + (kill-buffer obuf)))) + +(defun create-file-buffer (filename) + "Create a suitably named buffer for visiting FILENAME, and return it. +FILENAME (sans directory) is used unchanged if that name is free; +otherwise a string <2> or <3> or ... is appended to get an unused name." + (let ((handler (find-file-name-handler filename 'create-file-buffer))) + (if handler + (funcall handler 'create-file-buffer filename) + (let ((lastname (file-name-nondirectory filename))) + (if (string= lastname "") + (setq lastname filename)) + (generate-new-buffer lastname))))) + +(defun generate-new-buffer (name) + "Create and return a buffer with a name based on NAME. +Choose the buffer's name using `generate-new-buffer-name'." + (get-buffer-create (generate-new-buffer-name name))) + +(defvar abbreviated-home-dir nil + "The user's homedir abbreviated according to `directory-abbrev-alist'.") + +(defun abbreviate-file-name (filename &optional hack-homedir) + "Return a version of FILENAME shortened using `directory-abbrev-alist'. +See documentation of variable `directory-abbrev-alist' for more information. +If optional argument HACK-HOMEDIR is non-nil, then this also substitutes +\"~\" for the user's home directory." + (let ((handler (find-file-name-handler filename 'abbreviate-file-name))) + (if handler + (funcall handler 'abbreviate-file-name filename hack-homedir) + ;; Get rid of the prefixes added by the automounter. + ;;(if (and (string-match automount-dir-prefix filename) + ;; (file-exists-p (file-name-directory + ;; (substring filename (1- (match-end 0)))))) + ;; (setq filename (substring filename (1- (match-end 0))))) + (let ((tail directory-abbrev-alist)) + ;; If any elt of directory-abbrev-alist matches this name, + ;; abbreviate accordingly. + (while tail + (if (string-match (car (car tail)) filename) + (setq filename + (concat (cdr (car tail)) (substring filename (match-end 0))))) + (setq tail (cdr tail)))) + (if hack-homedir + (progn + ;; Compute and save the abbreviated homedir name. + ;; We defer computing this until the first time it's needed, to + ;; give time for directory-abbrev-alist to be set properly. + ;; We include a slash at the end, to avoid spurious matches + ;; such as `/usr/foobar' when the home dir is `/usr/foo'. + (or abbreviated-home-dir + (setq abbreviated-home-dir + (let ((abbreviated-home-dir "$foo")) + (concat "\\`" (regexp-quote (abbreviate-file-name + (expand-file-name "~"))) + "\\(/\\|\\'\\)")))) + ;; If FILENAME starts with the abbreviated homedir, + ;; make it start with `~' instead. + (if (and (string-match abbreviated-home-dir filename) + ;; If the home dir is just /, don't change it. + (not (and (= (match-end 0) 1) ;#### unix-specific + (= (aref filename 0) ?/))) + (not (and (or (eq system-type 'ms-dos) + (eq system-type 'windows-nt)) + (save-match-data + (string-match "^[a-zA-Z]:/$" filename))))) + (setq filename + (concat "~" + (substring filename + (match-beginning 1) (match-end 1)) + (substring filename (match-end 0))))))) + filename))) + +(defcustom find-file-not-true-dirname-list nil + "*List of logical names for which visiting shouldn't save the true dirname. +On VMS, when you visit a file using a logical name that searches a path, +you may or may not want the visited file name to record the specific +directory where the file was found. If you *do not* want that, add the logical +name to this list as a string." + :type '(repeat (string :tag "Name")) + :group 'find-file) + +;; This function is needed by FSF vc.el. I hope somebody can make it +;; work for XEmacs. -sb. +(defun find-buffer-visiting (filename) + "Return the buffer visiting file FILENAME (a string). +This is like `get-file-buffer', except that it checks for any buffer +visiting the same file, possibly under a different name. +If there is no such live buffer, return nil." + (let ((buf (get-file-buffer filename)) + (truename (abbreviate-file-name (file-truename filename)))) + (or buf + (let ((list (buffer-list)) found) + (while (and (not found) list) + (save-excursion + (set-buffer (car list)) + (if (and buffer-file-name + (string= buffer-file-truename truename)) + (setq found (car list)))) + (setq list (cdr list))) + found) + (let ((number (nthcdr 10 (file-attributes truename))) + (list (buffer-list)) found) + (and buffer-file-numbers-unique + number + (while (and (not found) list) + (save-excursion + (set-buffer (car list)) + (if (and buffer-file-number + (equal buffer-file-number number) + ;; Verify this buffer's file number + ;; still belongs to its file. + (file-exists-p buffer-file-name) + (equal (nthcdr 10 (file-attributes buffer-file-name)) + number)) + (setq found (car list)))) + (setq list (cdr list)))) + found)))) + +(defun insert-file-contents-literally (filename &optional visit beg end replace) + "Like `insert-file-contents', q.v., but only reads in the file. +A buffer may be modified in several ways after reading into the buffer due +to advanced Emacs features, such as file-name-handlers, format decoding, +find-file-hooks, etc. + This function ensures that none of these modifications will take place." + (let ((file-name-handler-alist nil) + (format-alist nil) + (after-insert-file-functions nil) + (find-buffer-file-type-function + (if (fboundp 'find-buffer-file-type) + (symbol-function 'find-buffer-file-type) + nil))) + (unwind-protect + (progn + (fset 'find-buffer-file-type (lambda (filename) t)) + (insert-file-contents filename visit beg end replace)) + (if find-buffer-file-type-function + (fset 'find-buffer-file-type find-buffer-file-type-function) + (fmakunbound 'find-buffer-file-type))))) + +(defun find-file-noselect (filename &optional nowarn rawfile) + "Read file FILENAME into a buffer and return the buffer. +If a buffer exists visiting FILENAME, return that one, but +verify that the file has not changed since visited or saved. +The buffer is not selected, just returned to the caller. +If NOWARN is non-nil, warning messages about several potential +problems will be suppressed." + (setq filename (abbreviate-file-name (expand-file-name filename))) + (if (file-directory-p filename) + (if find-file-run-dired + (dired-noselect (if find-file-use-truenames + (abbreviate-file-name (file-truename filename)) + filename)) + (error "%s is a directory." filename)) + (let* ((buf (get-file-buffer filename)) +; (truename (abbreviate-file-name (file-truename filename))) + (number (nthcdr 10 (file-attributes (file-truename filename)))) +; (number (and buffer-file-truename +; (nthcdr 10 (file-attributes buffer-file-truename)))) +; ;; Find any buffer for a file which has same truename. +; (other (and (not buf) (find-buffer-visiting filename))) + (error nil)) + +; ;; Let user know if there is a buffer with the same truename. +; (if (and (not buf) same-truename (not nowarn)) +; (message "%s and %s are the same file (%s)" +; filename (buffer-file-name same-truename) +; truename) +; (if (and (not buf) same-number (not nowarn)) +; (message "%s and %s are the same file" +; filename (buffer-file-name same-number)))) +; ;; Optionally also find that buffer. +; (if (or find-file-existing-other-name find-file-visit-truename) +; (setq buf (or same-truename same-number))) + + (when (and buf + (or find-file-compare-truenames find-file-use-truenames) + (not nowarn)) + (save-excursion + (set-buffer buf) + (if (not (string-equal buffer-file-name filename)) + (message "%s and %s are the same file (%s)" + filename buffer-file-name + buffer-file-truename)))) + + (if buf + (or nowarn + (verify-visited-file-modtime buf) + (cond ((not (file-exists-p filename)) + (error "File %s no longer exists!" filename)) + ;; Certain files should be reverted automatically + ;; if they have changed on disk and not in the buffer. + ((and (not (buffer-modified-p buf)) + (let (found) + (dolist (rx revert-without-query found) + (when (string-match rx filename) + (setq found t))))) + (with-current-buffer buf + (message "Reverting file %s..." filename) + (revert-buffer t t) + (message "Reverting file %s... done" filename))) + ((yes-or-no-p + (if (string= (file-name-nondirectory filename) + (buffer-name buf)) + (format + (if (buffer-modified-p buf) + (gettext "File %s changed on disk. Discard your edits? ") + (gettext "File %s changed on disk. Reread from disk? ")) + (file-name-nondirectory filename)) + (format + (if (buffer-modified-p buf) + (gettext "File %s changed on disk. Discard your edits in %s? ") + (gettext "File %s changed on disk. Reread from disk into %s? ")) + (file-name-nondirectory filename) + (buffer-name buf)))) + (save-excursion + (set-buffer buf) + (revert-buffer t t))))) + ;; Else: we must create a new buffer for filename + (save-excursion +;;; The truename stuff makes this obsolete. +;;; (let* ((link-name (car (file-attributes filename))) +;;; (linked-buf (and (stringp link-name) +;;; (get-file-buffer link-name)))) +;;; (if (bufferp linked-buf) +;;; (message "Symbolic link to file in buffer %s" +;;; (buffer-name linked-buf)))) + (setq buf (create-file-buffer filename)) + (set-buffer-major-mode buf) + (set-buffer buf) + (erase-buffer) + (if rawfile + (condition-case () + (insert-file-contents-literally filename t) + (file-error + ;; Unconditionally set error + (setq error t))) + (condition-case e + (insert-file-contents filename t) + (file-error + ;; Run find-file-not-found-hooks until one returns non-nil. + (or (run-hook-with-args-until-success 'find-file-not-found-hooks) + ;; If they fail too, set error. + (setq error e))))) + ;; Find the file's truename, and maybe use that as visited name. + ;; automatically computed in XEmacs. +; (setq buffer-file-truename truename) + (setq buffer-file-number number) + ;; On VMS, we may want to remember which directory in a search list + ;; the file was found in. + (and (eq system-type 'vax-vms) + (let (logical) + (if (string-match ":" (file-name-directory filename)) + (setq logical (substring (file-name-directory filename) + 0 (match-beginning 0)))) + (not (member logical find-file-not-true-dirname-list))) + (setq buffer-file-name buffer-file-truename)) +; (if find-file-visit-truename +; (setq buffer-file-name +; (setq filename +; (expand-file-name buffer-file-truename)))) + (and find-file-use-truenames + ;; This should be in C. Put pathname abbreviations that have + ;; been explicitly requested back into the pathname. Most + ;; importantly, strip out automounter /tmp_mnt directories so + ;; that auto-save will work + (setq buffer-file-name (abbreviate-file-name buffer-file-name))) + ;; Set buffer's default directory to that of the file. + (setq default-directory (file-name-directory buffer-file-name)) + ;; Turn off backup files for certain file names. Since + ;; this is a permanent local, the major mode won't eliminate it. + (and (not (funcall backup-enable-predicate buffer-file-name)) + (progn + (make-local-variable 'backup-inhibited) + (setq backup-inhibited t))) + (if rawfile + nil + (after-find-file error (not nowarn)) + (setq buf (current-buffer))))) + buf))) + +(defvar after-find-file-from-revert-buffer nil) + +(defun after-find-file (&optional error warn noauto + after-find-file-from-revert-buffer + nomodes) + "Called after finding a file and by the default revert function. +Sets buffer mode, parses local variables. +Optional args ERROR, WARN, and NOAUTO: ERROR non-nil means there was an +error in reading the file. WARN non-nil means warn if there +exists an auto-save file more recent than the visited file. +NOAUTO means don't mess with auto-save mode. +Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER non-nil + means this call was from `revert-buffer'. +Fifth arg NOMODES non-nil means don't alter the file's modes. +Finishes by calling the functions in `find-file-hooks'." + (setq buffer-read-only (not (file-writable-p buffer-file-name))) + (if noninteractive + nil + (let* (not-serious + (msg + (cond ((and error (file-attributes buffer-file-name)) + (setq buffer-read-only t) + (gettext "File exists, but cannot be read.")) + ((not buffer-read-only) + (if (and warn + (file-newer-than-file-p (make-auto-save-file-name) + buffer-file-name)) + (format "%s has auto save data; consider M-x recover-file" + (setq not-serious t) + (if error (gettext "(New file)") nil)))) + ((not error) + (setq not-serious t) + (gettext "Note: file is write protected")) + ((file-attributes (directory-file-name default-directory)) + (gettext "File not found and directory write-protected")) + ((file-exists-p (file-name-directory buffer-file-name)) + (setq buffer-read-only nil)) + (t + ;; If the directory the buffer is in doesn't exist, + ;; offer to create it. It's better to do this now + ;; than when we save the buffer, because we want + ;; autosaving to work. + (setq buffer-read-only nil) + ;; XEmacs + (or (file-exists-p (file-name-directory buffer-file-name)) + (if (yes-or-no-p + (format + "The directory containing %s does not exist. Create? " + (abbreviate-file-name buffer-file-name))) + (make-directory (file-name-directory + buffer-file-name) + t))) + nil)))) + (if msg + (progn + (message msg) + (or not-serious (sit-for 1 t))))) + (if (and auto-save-default (not noauto)) + (auto-save-mode t))) + (unless nomodes + (normal-mode t) + (run-hooks 'find-file-hooks))) + +(defun normal-mode (&optional find-file) + "Choose the major mode for this buffer automatically. +Also sets up any specified local variables of the file. +Uses the visited file name, the -*- line, and the local variables spec. + +This function is called automatically from `find-file'. In that case, +we may set up specified local variables depending on the value of +`enable-local-variables': if it is t, we do; if it is nil, we don't; +otherwise, we query. `enable-local-variables' is ignored if you +run `normal-mode' explicitly." + (interactive) + (or find-file (funcall (or default-major-mode 'fundamental-mode))) + (and (condition-case err + (progn (set-auto-mode) + t) + (error (message "File mode specification error: %s" + (prin1-to-string err)) + nil)) + (condition-case err + (hack-local-variables (not find-file)) + (error (message "File local-variables error: %s" + (prin1-to-string err)))))) + +(defvar auto-mode-alist + '(("\\.te?xt\\'" . text-mode) + ("\\.[ch]\\'" . c-mode) + ("\\.el\\'" . emacs-lisp-mode) + ("\\.\\([CH]\\|cc\\|hh\\)\\'" . c++-mode) + ("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode) + ("\\.java\\'" . java-mode) + ("\\.f\\(or\\)?\\'" . fortran-mode) + ("\\.F\\(OR\\)?\\'" . fortran-mode) + ("\\.[fF]90\\'" . f90-mode) +;;; Less common extensions come here +;;; so more common ones above are found faster. + ("\\.p[lm]\\'" . perl-mode) + ("\\.py\\'" . python-mode) + ("\\.texi\\(nfo\\)?\\'" . texinfo-mode) + ("\\.ad[abs]\\'" . ada-mode) + ("\\.c?l\\(i?sp\\)?\\'" . lisp-mode) + ("\\.p\\(as\\)?\\'" . pascal-mode) + ("\\.ltx\\'" . latex-mode) + ("\\.[sS]\\'" . asm-mode) + ("[Cc]hange.?[Ll]og?\\(.[0-9]+\\)?\\'" . change-log-mode) + ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode) + ("\\.scm\\(\\.[0-9]*\\)?\\'" . scheme-mode) + ("\\.e\\'" . eiffel-mode) + ("\\.mss\\'" . scribe-mode) + ("\\.m\\([mes]\\|an\\)\\'" . nroff-mode) + ("\\.icn\\'" . icon-mode) + ("\\.\\([ckz]?sh\\|shar\\)\\'" . sh-mode) + ("/\\.\\(bash_\\|z\\)?\\(profile\\|login\||logout\\)\\'" . sh-mode) + ("/\\.\\([ckz]sh\\|bash\\|tcsh\\|es\\|xinit\\|startx\\)rc\\'" . sh-mode) + ("/\\.\\([kz]shenv\\|xsession\\)\\'" . sh-mode) +;;; The following should come after the ChangeLog pattern +;;; for the sake of ChangeLog.1, etc. +;;; and after the .scm.[0-9] pattern too. + ("\\.[12345678]\\'" . nroff-mode) + ("\\.[tT]e[xX]\\'" . tex-mode) + ("\\.\\(sty\\|cls\\|bbl\\)\\'" . latex-mode) + ("\\.bib\\'" . bibtex-mode) + ("\\.article\\'" . text-mode) + ("\\.letter\\'" . text-mode) + ("\\.\\(tcl\\|exp\\)\\'" . tcl-mode) + ("\\.wrl\\'" . vrml-mode) + ("\\.awk\\'" . awk-mode) + ("\\.prolog\\'" . prolog-mode) + ("\\.tar\\'" . tar-mode) + ("\\.\\(arc\\|zip\\|lzh\\|zoo\\)\\'" . archive-mode) + ;; Mailer puts message to be edited in + ;; /tmp/Re.... or Message + ("^/tmp/Re" . text-mode) + ("/Message[0-9]*\\'" . text-mode) + ("/drafts/[0-9]+\\'" . mh-letter-mode) + ;; some news reader is reported to use this + ("^/tmp/fol/" . text-mode) + ("\\.y\\'" . c-mode) + ("\\.lex\\'" . c-mode) + ("\\.m\\'" . objc-mode) + ("\\.oak\\'" . scheme-mode) + ("\\.s?html?\\'" . html-mode) + ("\\.htm?l?3\\'" . html3-mode) + ("\\.\\(sgml?\\|dtd\\)\\'" . sgml-mode) + ("\\.c?ps\\'" . postscript-mode) + ;; .emacs following a directory delimiter + ;; in either Unix or VMS syntax. + ("[]>:/]\\..*emacs\\'" . emacs-lisp-mode) + ;; _emacs following a directory delimiter + ;; in MsDos syntax + ("[:/]_emacs\\'" . emacs-lisp-mode) + ("\\.m4\\'" . autoconf-mode) + ("configure\\.in\\'" . autoconf-mode) + ("\\.ml\\'" . lisp-mode) + ("\\.ma?k\\'" . makefile-mode) + ("[Mm]akefile\\(\\.\\|\\'\\)" . makefile-mode) + ("\\.X\\(defaults\\|environment\\|resources\\|modmap\\)\\'" . xrdb-mode) + ("/app-defaults/" . xrdb-mode) + ("\\.[^/]*wm\\'" . winmgr-mode) + ("\\.[^/]*wm2?rc" . winmgr-mode) + ("\\.[Jj][Pp][Ee]?[Gg]\\'" . image-mode) + ("\\.[Pp][Nn][Gg]\\'" . image-mode) + ("\\.[Gg][Ii][Ff]\\'" . image-mode) + ) +"Alist of filename patterns vs. corresponding major mode functions. +Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL). +\(NON-NIL stands for anything that is not nil; the value does not matter.) +Visiting a file whose name matches REGEXP specifies FUNCTION as the +mode function to use. FUNCTION will be called, unless it is nil. + +If the element has the form (REGEXP FUNCTION NON-NIL), then after +calling FUNCTION (if it's not nil), we delete the suffix that matched +REGEXP and search the list again for another match.") + +(defconst interpreter-mode-alist + '(("^#!.*csh" . sh-mode) + ("^#!.*sh\\b" . sh-mode) + ("^#!.*\\b\\(scope\\|wish\\|tcl\\|expect\\)" . tcl-mode) + ("perl" . perl-mode) + ("python" . python-mode) + ("awk\\b" . awk-mode) + ("rexx" . rexx-mode) + ("scm" . scheme-mode) + ("^:" . sh-mode)) + "Alist mapping interpreter names to major modes. +This alist is used to guess the major mode of a file based on the +contents of the first line. This line often contains something like: +#!/bin/sh +but may contain something more imaginative like +#! /bin/env python +or +eval 'exec perl -w -S $0 ${1+\"$@\"}'. + +Each alist element looks like (INTERPRETER . MODE). +The car of each element is a regular expression which is compared +with the name of the interpreter specified in the first line. +If it matches, mode MODE is selected.") + +(defconst inhibit-first-line-modes-regexps (purecopy '("\\.tar\\'")) + "List of regexps; if one matches a file name, don't look for `-*-'.") + +(defconst inhibit-first-line-modes-suffixes nil + "List of regexps for what to ignore, for `inhibit-first-line-modes-regexps'. +When checking `inhibit-first-line-modes-regexps', we first discard +from the end of the file name anything that matches one of these regexps.") + +(defvar user-init-file + "" ; set by command-line + "File name including directory of user's initialization file.") + +(defun set-auto-mode () + "Select major mode appropriate for current buffer. +This checks for a -*- mode tag in the buffer's text, +compares the filename against the entries in `auto-mode-alist', +or checks the interpreter that runs this file against +`interpreter-mode-alist'. + +It does not check for the `mode:' local variable in the +Local Variables section of the file; for that, use `hack-local-variables'. + +If `enable-local-variables' is nil, this function does not check for a +-*- mode tag." + (save-excursion + ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*- + ;; Do this by calling the hack-local-variables helper to avoid redundancy. + ;; We bind enable-local-variables to nil this time because we're going to + ;; call hack-local-variables-prop-line again later, "for real." + (or (let ((enable-local-variables nil)) + (hack-local-variables-prop-line nil)) + ;; It's not in the -*- line, so check the auto-mode-alist, unless + ;; this buffer isn't associated with a file. + (null buffer-file-name) + (let ((name (file-name-sans-versions buffer-file-name)) + (keep-going t)) + (while keep-going + (setq keep-going nil) + (let ((alist auto-mode-alist) + (mode nil)) + ;; Find first matching alist entry. + (let ((case-fold-search + (memq system-type '(vax-vms windows-nt)))) + (while (and (not mode) alist) + (if (string-match (car (car alist)) name) + (if (and (consp (cdr (car alist))) + (nth 2 (car alist))) + (progn + (setq mode (car (cdr (car alist))) + name (substring name 0 (match-beginning 0)) + keep-going t)) + (setq mode (cdr (car alist)) + keep-going nil))) + (setq alist (cdr alist)))) + ;; If we can't deduce a mode from the file name, + ;; look for an interpreter specified in the first line. + (if (and (null mode) + (save-excursion ; XEmacs + (goto-char (point-min)) + (looking-at "#!"))) + (let ((firstline + (buffer-substring + (point-min) + (save-excursion + (goto-char (point-min)) (end-of-line) (point))))) + (setq alist interpreter-mode-alist) + (while alist + (if (string-match (car (car alist)) firstline) + (progn + (setq mode (cdr (car alist))) + (setq alist nil)) + (setq alist (cdr alist)))))) + (if mode + (funcall mode)) + )))))) + +(defvar hack-local-variables-hook nil + "Normal hook run after processing a file's local variables specs. +Major modes can use this to examine user-specified local variables +in order to initialize other data structure based on them. + +This hook runs even if there were no local variables or if their +evaluation was suppressed. See also `enable-local-variables' and +`enable-local-eval'.") + +(defun hack-local-variables (&optional force) + "Parse, and bind or evaluate as appropriate, any local variables +for current buffer." + ;; Don't look for -*- if this file name matches any + ;; of the regexps in inhibit-first-line-modes-regexps. + (if (or (null buffer-file-name) ; don't lose if buffer has no file! + (not (let ((temp inhibit-first-line-modes-regexps) + (name (if buffer-file-name + (file-name-sans-versions buffer-file-name) + (buffer-name)))) + (while (let ((sufs inhibit-first-line-modes-suffixes)) + (while (and sufs (not + (string-match (car sufs) name))) + (setq sufs (cdr sufs))) + sufs) + (setq name (substring name 0 (match-beginning 0)))) + (while (and temp + (not (string-match (car temp) name))) + (setq temp (cdr temp)) + temp)))) + (progn + ;; Look for variables in the -*- line. + (hack-local-variables-prop-line force) + ;; Look for "Local variables:" block in last page. + (hack-local-variables-last-page force))) + (run-hooks 'hack-local-variables-hook)) + +;;; Local variables may be specified in the last page of the file (within 3k +;;; from the end of the file and after the last ^L) in the form +;;; +;;; Local variables: +;;; variable-name: variable-value +;;; end: +;;; +;;; The lines may begin with a common prefix, like ";;; " in the above +;;; example. They may also have a common suffix (" */" for example). In +;;; this form, the local variable "mode" can be used to change the major +;;; mode, and the local variable "eval" can be used to evaluate an arbitrary +;;; form. +;;; +;;; Local variables may also be specified in the first line of the file. +;;; Embedded in this line are a pair of "-*-" sequences. What lies between +;;; them are variable-name/variable-value pairs, like: +;;; +;;; -*- mode: emacs-lisp -*- +;;; or -*- mode: postscript; version-control: never -*- +;;; or -*- tags-file-name: "/foo/bar/TAGS" -*- +;;; +;;; The local variable "eval" is not used with this form. For hysterical +;;; reasons, the syntax "-*- modename -*-" is allowed as well. +;;; + +(defun hack-local-variables-p (modeline) + (or (eq enable-local-variables t) + (and enable-local-variables + (save-window-excursion + (condition-case nil + (switch-to-buffer (current-buffer)) + (error + ;; If we fail to switch in the selected window, + ;; it is probably a minibuffer. + ;; So try another window. + (condition-case nil + (switch-to-buffer-other-window (current-buffer)) + (error + (switch-to-buffer-other-frame (current-buffer)))))) + (or modeline (save-excursion + (beginning-of-line) + (set-window-start (selected-window) (point)))) + (y-or-n-p (format + "Set local variables as specified %s of %s? " + (if modeline "in -*- line" "at end") + (if buffer-file-name + (file-name-nondirectory buffer-file-name) + (concat "buffer " (buffer-name))))))))) + +(defun hack-local-variables-last-page (&optional force) + ;; Set local variables set in the "Local Variables:" block of the last page. + (save-excursion + (goto-char (point-max)) + (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move) + (if (let ((case-fold-search t)) + (and (search-forward "Local Variables:" nil t) + (or force + (hack-local-variables-p nil)))) + (let ((continue t) + prefix prefixlen suffix beg + (enable-local-eval enable-local-eval)) + ;; The prefix is what comes before "local variables:" in its line. + ;; The suffix is what comes after "local variables:" in its line. + (skip-chars-forward " \t") + (or (eolp) + (setq suffix (buffer-substring (point) + (progn (end-of-line) (point))))) + (goto-char (match-beginning 0)) + (or (bolp) + (setq prefix + (buffer-substring (point) + (progn (beginning-of-line) (point))))) + (if prefix (setq prefixlen (length prefix) + prefix (regexp-quote prefix))) + (if suffix (setq suffix (concat (regexp-quote suffix) "$"))) + (while continue + ;; Look at next local variable spec. + (if selective-display (re-search-forward "[\n\C-m]") + (forward-line 1)) + ;; Skip the prefix, if any. + (if prefix + (if (looking-at prefix) + (forward-char prefixlen) + (error "Local variables entry is missing the prefix"))) + ;; Find the variable name; strip whitespace. + (skip-chars-forward " \t") + (setq beg (point)) + (skip-chars-forward "^:\n") + (if (eolp) (error "Missing colon in local variables entry")) + (skip-chars-backward " \t") + (let* ((str (buffer-substring beg (point))) + (var (read str)) + val) + ;; Setting variable named "end" means end of list. + (if (string-equal (downcase str) "end") + (setq continue nil) + ;; Otherwise read the variable value. + (skip-chars-forward "^:") + (forward-char 1) + (setq val (read (current-buffer))) + (skip-chars-backward "\n") + (skip-chars-forward " \t") + (or (if suffix (looking-at suffix) (eolp)) + (error "Local variables entry is terminated incorrectly")) + ;; Set the variable. "Variables" mode and eval are funny. + (hack-one-local-variable var val)))))))) + +;; jwz - New Version 20.1/19.15 +(defun hack-local-variables-prop-line (&optional force) + ;; Set local variables specified in the -*- line. + ;; Returns t if mode was set. + (let ((result nil)) + (save-excursion + (goto-char (point-min)) + (skip-chars-forward " \t\n\r") + (let ((end (save-excursion + ;; If the file begins with "#!" + ;; (un*x exec interpreter magic), look + ;; for mode frobs in the first two + ;; lines. You cannot necessarily + ;; put them in the first line of + ;; such a file without screwing up + ;; the interpreter invocation. + (end-of-line (and (looking-at "^#!") 2)) + (point)))) + ;; Parse the -*- line into the `result' alist. + (cond ((not (search-forward "-*-" end t)) + ;; doesn't have one. + (setq force t)) + ((looking-at "[ \t]*\\([^ \t\n\r:;]+\\)\\([ \t]*-\\*-\\)") + ;; Antiquated form: "-*- ModeName -*-". + (setq result + (list (cons 'mode + (intern (buffer-substring + (match-beginning 1) + (match-end 1))))) + )) + (t + ;; Usual form: '-*-' [ ':' ';' ]* '-*-' + ;; (last ";" is optional). + (save-excursion + (if (search-forward "-*-" end t) + (setq end (- (point) 3)) + (error "-*- not terminated before end of line"))) + (while (< (point) end) + (or (looking-at "[ \t]*\\([^ \t\n:]+\\)[ \t]*:[ \t]*") + (error "malformed -*- line")) + (goto-char (match-end 0)) + ;; There used to be a downcase here, + ;; but the manual didn't say so, + ;; and people want to set var names that aren't all lc. + (let ((key (intern (buffer-substring + (match-beginning 1) + (match-end 1)))) + (val (save-restriction + (narrow-to-region (point) end) + (read (current-buffer))))) + ;; Case sensitivity! Icepicks in my forehead! + (if (equal (downcase (symbol-name key)) "mode") + (setq key 'mode)) + (setq result (cons (cons key val) result)) + (skip-chars-forward " \t;"))) + (setq result (nreverse result)))))) + + (let ((set-any-p (or force (hack-local-variables-p t))) + (mode-p nil)) + (while result + (let ((key (car (car result))) + (val (cdr (car result)))) + (cond ((eq key 'mode) + (and enable-local-variables + (setq mode-p t) + (funcall (intern (concat (downcase (symbol-name val)) + "-mode"))))) + (set-any-p + (hack-one-local-variable key val)) + (t + nil))) + (setq result (cdr result))) + mode-p))) + +(defconst ignored-local-variables + (list 'enable-local-eval) + "Variables to be ignored in a file's local variable spec.") + +;; Get confirmation before setting these variables as locals in a file. +(put 'debugger 'risky-local-variable t) +(put 'enable-local-eval 'risky-local-variable t) +(put 'ignored-local-variables 'risky-local-variable t) +(put 'eval 'risky-local-variable t) +(put 'file-name-handler-alist 'risky-local-variable t) +(put 'minor-mode-map-alist 'risky-local-variable t) +(put 'after-load-alist 'risky-local-variable t) +(put 'buffer-file-name 'risky-local-variable t) +(put 'buffer-auto-save-file-name 'risky-local-variable t) +(put 'buffer-file-truename 'risky-local-variable t) +(put 'exec-path 'risky-local-variable t) +(put 'load-path 'risky-local-variable t) +(put 'exec-directory 'risky-local-variable t) +(put 'process-environment 'risky-local-variable t) +;; Don't wait for outline.el to be loaded, for the sake of outline-minor-mode. +(put 'outline-level 'risky-local-variable t) +(put 'rmail-output-file-alist 'risky-local-variable t) + +;; This one is safe because the user gets to check it before it is used. +(put 'compile-command 'safe-local-variable t) + +;(defun hack-one-local-variable-quotep (exp) +; (and (consp exp) (eq (car exp) 'quote) (consp (cdr exp)))) + +;; "Set" one variable in a local variables spec. +;; A few variable names are treated specially. +(defun hack-one-local-variable (var val) + (cond ((eq var 'mode) + (funcall (intern (concat (downcase (symbol-name val)) + "-mode")))) + ((memq var ignored-local-variables) + nil) + ;; "Setting" eval means either eval it or do nothing. + ;; Likewise for setting hook variables. + ((or (get var 'risky-local-variable) + (and + (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|-command$" + (symbol-name var)) + (not (get var 'safe-local-variable)))) +; ;; Permit evaling a put of a harmless property +; ;; if the args do nothing tricky. +; (if (or (and (eq var 'eval) +; (consp val) +; (eq (car val) 'put) +; (hack-one-local-variable-quotep (nth 1 val)) +; (hack-one-local-variable-quotep (nth 2 val)) +; ;; Only allow safe values of lisp-indent-hook; +; ;; not functions. +; (or (numberp (nth 3 val)) +; (equal (nth 3 val) ''defun)) +; (memq (nth 1 (nth 2 val)) +; '(lisp-indent-hook))) + (if (and (not (zerop (user-uid))) + (or (eq enable-local-eval t) + (and enable-local-eval + (save-window-excursion + (switch-to-buffer (current-buffer)) + (save-excursion + (beginning-of-line) + (set-window-start (selected-window) (point))) + (setq enable-local-eval + (y-or-n-p (format "Process `eval' or hook local variables in file %s? " + (file-name-nondirectory buffer-file-name)))))))) + (if (eq var 'eval) + (save-excursion (eval val)) + (make-local-variable var) + (set var val)) + (message "Ignoring `eval:' in file's local variables"))) + ;; Ordinary variable, really set it. + (t (make-local-variable var) + (set var val)))) + +(defun set-visited-file-name (filename) + "Change name of file visited in current buffer to FILENAME. +The next time the buffer is saved it will go in the newly specified file. +nil or empty string as argument means make buffer not be visiting any file. +Remember to delete the initial contents of the minibuffer +if you wish to pass an empty string as the argument." + (interactive "FSet visited file name: ") + (if (buffer-base-buffer) + (error "An indirect buffer cannot visit a file")) + (let (truename) + (if filename + (setq filename + (if (string-equal filename "") + nil + (expand-file-name filename)))) + (if filename + (progn + (setq truename (file-truename filename)) + ;; #### Do we need to check if truename is non-nil? + (if find-file-use-truenames + (setq filename truename)))) + (or (equal filename buffer-file-name) + (progn + (and filename (lock-buffer filename)) + (unlock-buffer))) + (setq buffer-file-name filename) + (if filename ; make buffer name reflect filename. + (let ((new-name (file-name-nondirectory buffer-file-name))) + (if (string= new-name "") + (error "Empty file name")) + (if (eq system-type 'vax-vms) + (setq new-name (downcase new-name))) + (setq default-directory (file-name-directory buffer-file-name)) + (or (string= new-name (buffer-name)) + (rename-buffer new-name t)))) + (setq buffer-backed-up nil) + (clear-visited-file-modtime) + (compute-buffer-file-truename) ; insert-file-contents does this too. +; ;; Abbreviate the file names of the buffer. +; (if truename +; (progn +; (setq buffer-file-truename (abbreviate-file-name truename)) +; (if find-file-visit-truename +; (setq buffer-file-name buffer-file-truename)))) + (setq buffer-file-number + (if filename + (nthcdr 10 (file-attributes buffer-file-name)) + nil))) + ;; write-file-hooks is normally used for things like ftp-find-file + ;; that visit things that are not local files as if they were files. + ;; Changing to visit an ordinary local file instead should flush the hook. + (kill-local-variable 'write-file-hooks) + (kill-local-variable 'after-save-hook) + (kill-local-variable 'local-write-file-hooks) + (kill-local-variable 'write-file-data-hooks) + (kill-local-variable 'revert-buffer-function) + (kill-local-variable 'backup-inhibited) + ;; If buffer was read-only because of version control, + ;; that reason is gone now, so make it writable. + (if (and (boundp 'vc-mode) vc-mode) + (setq buffer-read-only nil)) + (kill-local-variable 'vc-mode) + ;; Turn off backup files for certain file names. + ;; Since this is a permanent local, the major mode won't eliminate it. + (and (not (funcall backup-enable-predicate buffer-file-name)) + (progn + (make-local-variable 'backup-inhibited) + (setq backup-inhibited t))) + (let ((oauto buffer-auto-save-file-name)) + ;; If auto-save was not already on, turn it on if appropriate. + (if (not buffer-auto-save-file-name) + (and buffer-file-name auto-save-default + (auto-save-mode t)) + ;; If auto save is on, start using a new name. + ;; We deliberately don't rename or delete the old auto save + ;; for the old visited file name. This is because perhaps + ;; the user wants to save the new state and then compare with the + ;; previous state from the auto save file. + (setq buffer-auto-save-file-name + (make-auto-save-file-name))) + ;; Rename the old auto save file if any. + (and oauto buffer-auto-save-file-name + (file-exists-p oauto) + (rename-file oauto buffer-auto-save-file-name t))) + (if buffer-file-name + (set-buffer-modified-p t)) + ;; #### ?? + (run-hooks 'after-set-visited-file-name-hooks)) + +(defun write-file (filename &optional confirm codesys) + "Write current buffer into file FILENAME. +Makes buffer visit that file, and marks it not modified. +If the buffer is already visiting a file, you can specify +a directory name as FILENAME, to write a file of the same +old name in that directory. +If optional second arg CONFIRM is non-nil, +ask for confirmation for overwriting an existing file. +Under XEmacs/Mule, optional third argument specifies the +coding system to use when encoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." +;; (interactive "FWrite file: ") + (interactive + (list (if buffer-file-name + (read-file-name "Write file: " + nil nil nil nil) + (read-file-name "Write file: " + (cdr (assq 'default-directory + (buffer-local-variables))) + nil nil (buffer-name))) + t + (if (and current-prefix-arg (featurep 'mule)) + (read-coding-system "Coding system: ")))) + (and (eq (current-buffer) mouse-grabbed-buffer) + (error "Can't write minibuffer window")) + (or (null filename) (string-equal filename "") + (progn + ;; If arg is just a directory, + ;; use same file name, but in that directory. + (if (and (file-directory-p filename) buffer-file-name) + (setq filename (concat (file-name-as-directory filename) + (file-name-nondirectory buffer-file-name)))) + (and confirm + (file-exists-p filename) + (or (y-or-n-p (format "File `%s' exists; overwrite? " filename)) + (error "Canceled"))) + (set-visited-file-name filename))) + (set-buffer-modified-p t) + (setq buffer-read-only nil) + (if codesys + (let ((buffer-file-coding-system (get-coding-system codesys))) + (save-buffer)) + (save-buffer))) + +(defun backup-buffer () + "Make a backup of the disk file visited by the current buffer, if appropriate. +This is normally done before saving the buffer the first time. +If the value is non-nil, it is the result of `file-modes' on the original file; +this means that the caller, after saving the buffer, should change the modes +of the new file to agree with the old modes." + (if buffer-file-name + (let ((handler (find-file-name-handler buffer-file-name 'backup-buffer))) + (if handler + (funcall handler 'backup-buffer) + (if (and make-backup-files + (not backup-inhibited) + (not buffer-backed-up) + (file-exists-p buffer-file-name) + (memq (aref (elt (file-attributes buffer-file-name) 8) 0) + '(?- ?l))) + (let ((real-file-name buffer-file-name) + backup-info backupname targets setmodes) + ;; If specified name is a symbolic link, chase it to the target. + ;; Thus we make the backups in the directory where the real file is. + (setq real-file-name (file-chase-links real-file-name)) + (setq backup-info (find-backup-file-name real-file-name) + backupname (car backup-info) + targets (cdr backup-info)) +;;; (if (file-directory-p buffer-file-name) +;;; (error "Cannot save buffer in directory %s" buffer-file-name)) + (if backup-info + (condition-case () + (let ((delete-old-versions + ;; If have old versions to maybe delete, + ;; ask the user to confirm now, before doing anything. + ;; But don't actually delete til later. + (and targets + (or (eq delete-old-versions t) + (eq delete-old-versions nil)) + (or delete-old-versions + (y-or-n-p (format "Delete excess backup versions of %s? " + real-file-name)))))) + ;; Actually write the back up file. + (condition-case () + (if (or file-precious-flag + ; (file-symlink-p buffer-file-name) + backup-by-copying + (and backup-by-copying-when-linked + (> (file-nlinks real-file-name) 1)) + (and backup-by-copying-when-mismatch + (let ((attr (file-attributes real-file-name))) + (or (nth 9 attr) + (not (file-ownership-preserved-p real-file-name)))))) + (condition-case () + (copy-file real-file-name backupname t t) + (file-error + ;; If copying fails because file BACKUPNAME + ;; is not writable, delete that file and try again. + (if (and (file-exists-p backupname) + (not (file-writable-p backupname))) + (delete-file backupname)) + (copy-file real-file-name backupname t t))) + ;; rename-file should delete old backup. + (rename-file real-file-name backupname t) + (setq setmodes (file-modes backupname))) + (file-error + ;; If trouble writing the backup, write it in ~. + (setq backupname (expand-file-name "~/%backup%~")) + (message "Cannot write backup file; backing up in ~/%%backup%%~") + (sleep-for 1) + (condition-case () + (copy-file real-file-name backupname t t) + (file-error + ;; If copying fails because file BACKUPNAME + ;; is not writable, delete that file and try again. + (if (and (file-exists-p backupname) + (not (file-writable-p backupname))) + (delete-file backupname)) + (copy-file real-file-name backupname t t))))) + (setq buffer-backed-up t) + ;; Now delete the old versions, if desired. + (if delete-old-versions + (while targets + (condition-case () + (delete-file (car targets)) + (file-error nil)) + (setq targets (cdr targets)))) + setmodes) + (file-error nil))))))))) + +(defun file-name-sans-versions (name &optional keep-backup-version) + "Return FILENAME sans backup versions or strings. +This is a separate procedure so your site-init or startup file can +redefine it. +If the optional argument KEEP-BACKUP-VERSION is non-nil, +we do not remove backup version numbers, only true file version numbers." + (let ((handler (find-file-name-handler name 'file-name-sans-versions))) + (if handler + (funcall handler 'file-name-sans-versions name keep-backup-version) + (substring name 0 + (if (eq system-type 'vax-vms) + ;; VMS version number is (a) semicolon, optional + ;; sign, zero or more digits or (b) period, option + ;; sign, zero or more digits, provided this is the + ;; second period encountered outside of the + ;; device/directory part of the file name. + (or (string-match ";[-+]?[0-9]*\\'" name) + (if (string-match "\\.[^]>:]*\\(\\.[-+]?[0-9]*\\)\\'" + name) + (match-beginning 1)) + (length name)) + (if keep-backup-version + (length name) + (or (string-match "\\.~[0-9.]+~\\'" name) + ;; XEmacs - VC uses extensions like ".~tagname~" or ".~1.1.5.2~" + (let ((pos (string-match "\\.~\\([^.~ \t]+\\|[0-9.]+\\)~\\'" name))) + (and pos + ;; #### - is this filesystem check too paranoid? + (file-exists-p (substring name 0 pos)) + pos)) + (string-match "~\\'" name) + (length name)))))))) + +(defun file-ownership-preserved-p (file) + "Returns t if deleting FILE and rewriting it would preserve the owner." + (let ((handler (find-file-name-handler file 'file-ownership-preserved-p))) + (if handler + (funcall handler 'file-ownership-preserved-p file) + (let ((attributes (file-attributes file))) + ;; Return t if the file doesn't exist, since it's true that no + ;; information would be lost by an (attempted) delete and create. + (or (null attributes) + (= (nth 2 attributes) (user-uid))))))) + +(defun file-name-sans-extension (filename) + "Return FILENAME sans final \"extension\". +The extension, in a file name, is the part that follows the last `.'." + (save-match-data + (let ((file (file-name-sans-versions (file-name-nondirectory filename))) + directory) + (if (string-match "\\.[^.]*\\'" file) + (if (setq directory (file-name-directory filename)) + (expand-file-name (substring file 0 (match-beginning 0)) + directory) + (substring file 0 (match-beginning 0))) + filename)))) + +(defun make-backup-file-name (file) + "Create the non-numeric backup file name for FILE. +This is a separate function so you can redefine it for customization." + (if (eq system-type 'ms-dos) + (let ((fn (file-name-nondirectory file))) + (concat (file-name-directory file) + (if (string-match "\\([^.]*\\)\\(\\..*\\)?" fn) + (substring fn 0 (match-end 1))) + ".bak")) + (concat file "~"))) + +(defun backup-file-name-p (file) + "Return non-nil if FILE is a backup file name (numeric or not). +This is a separate function so you can redefine it for customization. +You may need to redefine `file-name-sans-versions' as well." + (if (eq system-type 'ms-dos) + (string-match "\\.bak\\'" file) + (string-match "~\\'" file))) + +;; This is used in various files. +;; The usage of bv-length is not very clean, +;; but I can't see a good alternative, +;; so as of now I am leaving it alone. +(defun backup-extract-version (fn) + "Given the name of a numeric backup file, return the backup number. +Uses the free variable `bv-length', whose value should be +the index in the name where the version number begins." + (declare (special bv-length)) + (if (and (string-match "[0-9]+~\\'" fn bv-length) + (= (match-beginning 0) bv-length)) + (string-to-int (substring fn bv-length -1)) + 0)) + +;; I believe there is no need to alter this behavior for VMS; +;; since backup files are not made on VMS, it should not get called. +(defun find-backup-file-name (fn) + "Find a file name for a backup file, and suggestions for deletions. +Value is a list whose car is the name for the backup file + and whose cdr is a list of old versions to consider deleting now. +If the value is nil, don't make a backup." + (let ((handler (find-file-name-handler fn 'find-backup-file-name))) + ;; Run a handler for this function so that ange-ftp can refuse to do it. + (if handler + (funcall handler 'find-backup-file-name fn) + (if (eq version-control 'never) + (list (make-backup-file-name fn)) + (let* ((base-versions (concat (file-name-nondirectory fn) ".~")) + ;; used by backup-extract-version: + (bv-length (length base-versions)) + possibilities + (versions nil) + (high-water-mark 0) + (deserve-versions-p nil) + (number-to-delete 0)) + (condition-case () + (setq possibilities (file-name-all-completions + base-versions + (file-name-directory fn)) + versions (sort (mapcar + #'backup-extract-version + possibilities) + '<) + high-water-mark (apply #'max 0 versions) + deserve-versions-p (or version-control + (> high-water-mark 0)) + number-to-delete (- (length versions) + kept-old-versions kept-new-versions -1)) + (file-error + (setq possibilities nil))) + (if (not deserve-versions-p) + (list (make-backup-file-name fn)) + (cons (concat fn ".~" (int-to-string (1+ high-water-mark)) "~") + (if (and (> number-to-delete 0) + ;; Delete nothing if there is overflow + ;; in the number of versions to keep. + (>= (+ kept-new-versions kept-old-versions -1) 0)) + (mapcar #'(lambda (n) + (concat fn ".~" (int-to-string n) "~")) + (let ((v (nthcdr kept-old-versions versions))) + (rplacd (nthcdr (1- number-to-delete) v) ()) + v)))))))))) + +(defun file-nlinks (filename) + "Return number of names file FILENAME has." + (car (cdr (file-attributes filename)))) + +(defun file-relative-name (filename &optional directory) + "Convert FILENAME to be relative to DIRECTORY (default: default-directory)." + (setq filename (expand-file-name filename) + directory (file-name-as-directory (expand-file-name + (or directory default-directory)))) + (let ((ancestor "")) + (while (not (string-match (concat "^" (regexp-quote directory)) filename)) + (setq directory (file-name-directory (substring directory 0 -1)) + ancestor (concat "../" ancestor))) + (concat ancestor (substring filename (match-end 0))))) + +(defun save-buffer (&optional args) + "Save current buffer in visited file if modified. Versions described below. + +By default, makes the previous version into a backup file + if previously requested or if this is the first save. +With 1 or 3 \\[universal-argument]'s, marks this version + to become a backup when the next save is done. +With 2 or 3 \\[universal-argument]'s, + unconditionally makes the previous version into a backup file. +With argument of 0, never makes the previous version into a backup file. + +If a file's name is FOO, the names of its numbered backup versions are + FOO.~i~ for various integers i. A non-numbered backup file is called FOO~. +Numeric backups (rather than FOO~) will be made if value of + `version-control' is not the atom `never' and either there are already + numeric versions of the file being backed up, or `version-control' is + non-nil. +We don't want excessive versions piling up, so there are variables + `kept-old-versions', which tells XEmacs how many oldest versions to keep, + and `kept-new-versions', which tells how many newest versions to keep. + Defaults are 2 old versions and 2 new. +`dired-kept-versions' controls dired's clean-directory (.) command. +If `delete-old-versions' is nil, system will query user + before trimming versions. Otherwise it does it silently." + (interactive "_p") + (let ((modp (buffer-modified-p)) + (large (> (buffer-size) 50000)) + (make-backup-files (or (and make-backup-files (not (eq args 0))) + (memq args '(16 64))))) + (and modp (memq args '(16 64)) (setq buffer-backed-up nil)) + (if (and modp large) (display-message + 'progress (format "Saving file %s..." + (buffer-file-name)))) + (basic-save-buffer) + (and modp (memq args '(4 64)) (setq buffer-backed-up nil)))) + +(defun delete-auto-save-file-if-necessary (&optional force) + "Delete auto-save file for current buffer if `delete-auto-save-files' is t. +Normally delete only if the file was written by this XEmacs +since the last real save, but optional arg FORCE non-nil means delete anyway." + (and buffer-auto-save-file-name delete-auto-save-files + (not (string= buffer-file-name buffer-auto-save-file-name)) + (or force (recent-auto-save-p)) + (progn + (condition-case () + (delete-file buffer-auto-save-file-name) + (file-error nil)) + (set-buffer-auto-saved)))) + +;; XEmacs change (from Sun) +;; used to communicate with continue-save-buffer: +(defvar continue-save-buffer-hooks-tail nil) + +;; Not in FSFmacs +(defun basic-write-file-data (realname truename) + ;; call the hooks until the bytes are put + ;; call write-region as a last resort + (let ((region-written nil) + (hooks write-file-data-hooks)) + (while (and hooks (not region-written)) + (setq region-written (funcall (car hooks) realname) + hooks (cdr hooks))) + (if (not region-written) + (write-region (point-min) (point-max) realname nil t truename)))) + +(put 'after-save-hook 'permanent-local t) +(defvar after-save-hook nil + "Normal hook that is run after a buffer is saved to its file. +These hooks are considered to pertain to the visited file. +So this list is cleared if you change the visited file name.") + +(defun files-fetch-hook-value (hook) + (let ((localval (symbol-value hook)) + (globalval (default-value hook))) + (if (memq t localval) + (setq localval (append (delq t localval) (delq t globalval)))) + localval)) + +(defun basic-save-buffer () + "Save the current buffer in its visited file, if it has been modified. +After saving the buffer, run `after-save-hook'." + (interactive) + (save-excursion + ;; In an indirect buffer, save its base buffer instead. + (if (buffer-base-buffer) + (set-buffer (buffer-base-buffer))) + (if (buffer-modified-p) + (let ((recent-save (recent-auto-save-p))) + ;; On VMS, rename file and buffer to get rid of version number. + (if (and (eq system-type 'vax-vms) + (not (string= buffer-file-name + (file-name-sans-versions buffer-file-name)))) + (let (buffer-new-name) + ;; Strip VMS version number before save. + (setq buffer-file-name + (file-name-sans-versions buffer-file-name)) + ;; Construct a (unique) buffer name to correspond. + (let ((buf (create-file-buffer (downcase buffer-file-name)))) + (setq buffer-new-name (buffer-name buf)) + (kill-buffer buf)) + (rename-buffer buffer-new-name))) + ;; If buffer has no file name, ask user for one. + (or buffer-file-name + (let ((filename + (expand-file-name + (read-file-name "File to save in: ") nil))) + (and (file-exists-p filename) + (or (y-or-n-p (format "File `%s' exists; overwrite? " + filename)) + (error "Canceled"))) + (set-visited-file-name filename))) + (or (verify-visited-file-modtime (current-buffer)) + (not (file-exists-p buffer-file-name)) + (yes-or-no-p + (format "%s has changed since visited or saved. Save anyway? " + (file-name-nondirectory buffer-file-name))) + (error "Save not confirmed")) + (save-restriction + (widen) + (and (> (point-max) 1) + (/= (char-after (1- (point-max))) ?\n) + (not (and (eq selective-display t) + (= (char-after (1- (point-max))) ?\r))) + (or (eq require-final-newline t) + (and require-final-newline + (y-or-n-p + (format "Buffer %s does not end in newline. Add one? " + (buffer-name))))) + (save-excursion + (goto-char (point-max)) + (insert ?\n))) + ;; + ;; Run the write-file-hooks until one returns non-null. + ;; Bind after-save-hook to nil while running the + ;; write-file-hooks so that if this function is called + ;; recursively (from inside a write-file-hook) the + ;; after-hooks will only get run once (from the + ;; outermost call). + ;; + ;; Ugh, have to duplicate logic of run-hook-with-args-until-success + (let ((hooks (append (files-fetch-hook-value 'write-contents-hooks) + (files-fetch-hook-value + 'local-write-file-hooks) + (files-fetch-hook-value 'write-file-hooks))) + (after-save-hook nil) + (local-write-file-hooks nil) + (write-contents-hooks nil) + (write-file-hooks nil) + done) + (while (and hooks + (let ((continue-save-buffer-hooks-tail hooks)) + (not (setq done (funcall (car hooks)))))) + (setq hooks (cdr hooks))) + ;; If a hook returned t, file is already "written". + ;; Otherwise, write it the usual way now. + (if (not done) + (basic-save-buffer-1))) + ;; XEmacs: next two clauses (buffer-file-number setting and + ;; set-file-modes) moved into basic-save-buffer-1. + ) + ;; If the auto-save file was recent before this command, + ;; delete it now. + (delete-auto-save-file-if-necessary recent-save) + ;; Support VC `implicit' locking. + (when (fboundp 'vc-after-save) + (vc-after-save)) + (run-hooks 'after-save-hook)) + (display-message 'no-log "(No changes need to be saved)")))) + +;; This does the "real job" of writing a buffer into its visited file +;; and making a backup file. This is what is normally done +;; but inhibited if one of write-file-hooks returns non-nil. +;; It returns a value to store in setmodes. +(defun basic-save-buffer-1 () + (let (setmodes tempsetmodes) + (if (not (file-writable-p buffer-file-name)) + (let ((dir (file-name-directory buffer-file-name))) + (if (not (file-directory-p dir)) + (error "%s is not a directory" dir) + (if (not (file-exists-p buffer-file-name)) + (error "Directory %s write-protected" dir) + (if (yes-or-no-p + (format "File %s is write-protected; try to save anyway? " + (file-name-nondirectory + buffer-file-name))) + (setq tempsetmodes t) + (error + "Attempt to save to a file which you aren't allowed to write")))))) + (or buffer-backed-up + (setq setmodes (backup-buffer))) + (let ((dir (file-name-directory buffer-file-name))) + (if (and file-precious-flag + (file-writable-p dir)) + ;; If file is precious, write temp name, then rename it. + ;; This requires write access to the containing dir, + ;; which is why we don't try it if we don't have that access. + (let ((realname buffer-file-name) + tempname nogood i succeed + (old-modtime (visited-file-modtime))) + (setq i 0) + (setq nogood t) + ;; Find the temporary name to write under. + (while nogood + (setq tempname (format "%s#tmp#%d" dir i)) + (setq nogood (file-exists-p tempname)) + (setq i (1+ i))) + (unwind-protect + (progn (clear-visited-file-modtime) + (write-region (point-min) (point-max) + tempname nil realname + buffer-file-truename) + (setq succeed t)) + ;; If writing the temp file fails, + ;; delete the temp file. + (or succeed + (progn + (delete-file tempname) + (set-visited-file-modtime old-modtime)))) + ;; Since we have created an entirely new file + ;; and renamed it, make sure it gets the + ;; right permission bits set. + (setq setmodes (file-modes buffer-file-name)) + ;; We succeeded in writing the temp file, + ;; so rename it. + (rename-file tempname buffer-file-name t)) + ;; If file not writable, see if we can make it writable + ;; temporarily while we write it. + ;; But no need to do so if we have just backed it up + ;; (setmodes is set) because that says we're superseding. + (cond ((and tempsetmodes (not setmodes)) + ;; Change the mode back, after writing. + (setq setmodes (file-modes buffer-file-name)) + (set-file-modes buffer-file-name 511))) + (basic-write-file-data buffer-file-name buffer-file-truename))) + (setq buffer-file-number + (if buffer-file-name + (nth 10 (file-attributes buffer-file-name)) + nil)) + (if setmodes + (condition-case () + (set-file-modes buffer-file-name setmodes) + (error nil))))) + +;; XEmacs change, from Sun +(defun continue-save-buffer () + "Provide a clean way for a write-file-hook to wrap AROUND +the execution of the remaining hooks and writing to disk. +Do not call this function except from a functions +on the write-file-hooks or write-contents-hooks list. +A hook that calls this function must return non-nil, +to signal completion to its caller. continue-save-buffer +always returns non-nil." + (let ((hooks (cdr (or continue-save-buffer-hooks-tail + (error + "continue-save-buffer called outside a write-file-hook!")))) + (done nil)) + ;; Do something like this: + ;; (let ((write-file-hooks hooks)) (basic-save-buffer)) + ;; First run the rest of the hooks. + (while (and hooks + (let ((continue-save-buffer-hooks-tail hooks)) + (not (setq done (funcall (car hooks)))))) + (setq hooks (cdr hooks))) + ;; + ;; If a hook returned t, file is already "written". + (if (not done) + (basic-save-buffer-1)) + 'continue-save-buffer)) + +(defcustom save-some-buffers-query-display-buffer xemacs-betaname + "*Non-nil makes `\\[save-some-buffers]' switch to the buffer offered for saving." + :type 'boolean + :group 'editing-basics) + +(defun save-some-buffers (&optional arg exiting) + "Save some modified file-visiting buffers. Asks user about each one. +Optional argument (the prefix) non-nil means save all with no questions. +Optional second argument EXITING means ask about certain non-file buffers + as well as about file buffers." + (interactive "P") + (save-excursion + (save-window-excursion + ;; This can bomb during autoloads generation + (when (and (not noninteractive) + save-some-buffers-query-display-buffer) + (delete-other-windows)) + ;; XEmacs - do not use queried flag + (let ((files-done + (map-y-or-n-p + (function + (lambda (buffer) + (and (buffer-modified-p buffer) + (not (buffer-base-buffer buffer)) + ;; XEmacs addition: + (not (symbol-value-in-buffer 'save-buffers-skip buffer)) + (or + (buffer-file-name buffer) + (and exiting + (progn + (set-buffer buffer) + (and buffer-offer-save (> (buffer-size) 0))))) + (if arg + t + (when save-some-buffers-query-display-buffer + (condition-case nil + (switch-to-buffer buffer t) + (error nil))) + (if (buffer-file-name buffer) + (format "Save file %s? " + (buffer-file-name buffer)) + (format "Save buffer %s? " + (buffer-name buffer))))))) + (function + (lambda (buffer) + (set-buffer buffer) + (condition-case () + (save-buffer) + (error nil)))) + (buffer-list) + '("buffer" "buffers" "save") + ;;instead of this we just say "yes all", "no all", etc. + ;;"save all the rest" + ;;"save only this buffer" "save no more buffers") + ;; this is rather bogus. --ben + ;; (it makes the dialog box too big, and you get an error + ;; "wrong type argument: framep, nil" when you hit q after + ;; choosing the option from the dialog box) +; (list (list ?\C-r (lambda (buf) +; (view-buffer buf) +; (setq view-exit-action +; '(lambda (ignore) +; (exit-recursive-edit))) +; (recursive-edit) +; ;; Return nil to ask about BUF again. +; nil) +; "display the current buffer")) + )) + (abbrevs-done + (and save-abbrevs abbrevs-changed + (progn + (if (or arg + (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name))) + (write-abbrev-file nil)) + ;; Don't keep bothering user if he says no. + (setq abbrevs-changed nil) + t)))) + (or (> files-done 0) abbrevs-done + (display-message 'no-log "(No files need saving)")))))) + + +(defun not-modified (&optional arg) + "Mark current buffer as unmodified, not needing to be saved. +With prefix arg, mark buffer as modified, so \\[save-buffer] will save. + +It is not a good idea to use this function in Lisp programs, because it +prints a message in the minibuffer. Instead, use `set-buffer-modified-p'." + (interactive "_P") + (if arg ;; rewritten for I18N3 snarfing + (display-message 'command "Modification-flag set") + (display-message 'command "Modification-flag cleared")) + (set-buffer-modified-p arg)) + +(defun toggle-read-only (&optional arg) + "Change whether this buffer is visiting its file read-only. +With arg, set read-only iff arg is positive." + (interactive "_P") + (setq buffer-read-only + (if (null arg) + (not buffer-read-only) + (> (prefix-numeric-value arg) 0))) + ;; Force modeline redisplay + (redraw-modeline)) + +(defun insert-file (filename &optional codesys) + "Insert contents of file FILENAME into buffer after point. +Set mark after the inserted text. + +Under XEmacs/Mule, optional second argument specifies the +coding system to use when decoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system. + +This function is meant for the user to run interactively. +Don't call it from programs! Use `insert-file-contents' instead. +\(Its calling sequence is different; see its documentation)." + (interactive "*fInsert file: \nZCoding system: ") + (if (file-directory-p filename) + (signal 'file-error (list "Opening input file" "file is a directory" + filename))) + (let ((tem + (if codesys + (let ((coding-system-for-read + (get-coding-system codesys))) + (insert-file-contents filename)) + (insert-file-contents filename)))) + (push-mark (+ (point) (car (cdr tem)))))) + +(defun append-to-file (start end filename &optional codesys) + "Append the contents of the region to the end of file FILENAME. +When called from a function, expects three arguments, +START, END and FILENAME. START and END are buffer positions +saying what text to write. +Under XEmacs/Mule, optional fourth argument specifies the +coding system to use when encoding the file. Interactively, +with a prefix argument, you will be prompted for the coding system." + (interactive "r\nFAppend to file: \nZCoding system: ") + (if codesys + (let ((buffer-file-coding-system (get-coding-system codesys))) + (write-region start end filename t)) + (write-region start end filename t))) + +(defun file-newest-backup (filename) + "Return most recent backup file for FILENAME or nil if no backups exist." + (let* ((filename (expand-file-name filename)) + (file (file-name-nondirectory filename)) + (dir (file-name-directory filename)) + (comp (file-name-all-completions file dir)) + newest) + (while comp + (setq file (concat dir (car comp)) + comp (cdr comp)) + (if (and (backup-file-name-p file) + (or (null newest) (file-newer-than-file-p file newest))) + (setq newest file))) + newest)) + +(defun rename-uniquely () + "Rename current buffer to a similar name not already taken. +This function is useful for creating multiple shell process buffers +or multiple mail buffers, etc." + (interactive) + (save-match-data + (let* ((base-name (if (and (string-match "<[0-9]+>\\'" (buffer-name)) + (not (and buffer-file-name + (string= (buffer-name) + (file-name-nondirectory + buffer-file-name))))) + ;; If the existing buffer name has a , + ;; which isn't part of the file name (if any), + ;; then get rid of that. + (substring (buffer-name) 0 (match-beginning 0)) + (buffer-name))) + (new-buf (generate-new-buffer base-name)) + (name (buffer-name new-buf))) + (kill-buffer new-buf) + (rename-buffer name) + (redraw-modeline)))) + +(defun make-directory-path (path) + "Create all the directories along path that don't exist yet." + (interactive "Fdirectory path to create: ") + (make-directory path t)) + +(defun make-directory (dir &optional parents) + "Create the directory DIR and any nonexistent parent dirs. +Interactively, the default choice of directory to create +is the current default directory for file names. +That is useful when you have visited a file in a nonexistent directory. + +Noninteractively, the second (optional) argument PARENTS says whether +to create parent directories if they don't exist." + (interactive (list (let ((current-prefix-arg current-prefix-arg)) + (read-directory-name "Create directory: ")) + current-prefix-arg)) + (let ((handler (find-file-name-handler dir 'make-directory))) + (if handler + (funcall handler 'make-directory dir parents) + (if (not parents) + (make-directory-internal dir) + (let ((dir (directory-file-name (expand-file-name dir))) + create-list) + (while (not (file-exists-p dir)) + (setq create-list (cons dir create-list) + dir (directory-file-name (file-name-directory dir)))) + (while create-list + (make-directory-internal (car create-list)) + (setq create-list (cdr create-list)))))))) + +(put 'revert-buffer-function 'permanent-local t) +(defvar revert-buffer-function nil + "Function to use to revert this buffer, or nil to do the default. +The function receives two arguments IGNORE-AUTO and NOCONFIRM, +which are the arguments that `revert-buffer' received.") + +(put 'revert-buffer-insert-file-contents-function 'permanent-local t) +(defvar revert-buffer-insert-file-contents-function nil + "Function to use to insert contents when reverting this buffer. +Gets two args, first the nominal file name to use, +and second, t if reading the auto-save file.") + +(defvar before-revert-hook nil + "Normal hook for `revert-buffer' to run before reverting. +If `revert-buffer-function' is used to override the normal revert +mechanism, this hook is not used.") + +(defvar after-revert-hook nil + "Normal hook for `revert-buffer' to run after reverting. +Note that the hook value that it runs is the value that was in effect +before reverting; that makes a difference if you have buffer-local +hook functions. + +If `revert-buffer-function' is used to override the normal revert +mechanism, this hook is not used.") + +(defvar revert-buffer-internal-hook nil + "Don't use this.") + +(defun revert-buffer (&optional ignore-auto noconfirm preserve-modes) + "Replace the buffer text with the text of the visited file on disk. +This undoes all changes since the file was visited or saved. +With a prefix argument, offer to revert from latest auto-save file, if +that is more recent than the visited file. + +This command also works for special buffers that contain text which +doesn't come from a file, but reflects some other data base instead: +for example, Dired buffers and buffer-list buffers. In these cases, +it reconstructs the buffer contents from the appropriate data base. + +When called from Lisp, the first argument is IGNORE-AUTO; only offer +to revert from the auto-save file when this is nil. Note that the +sense of this argument is the reverse of the prefix argument, for the +sake of backward compatibility. IGNORE-AUTO is optional, defaulting +to nil. + +Optional second argument NOCONFIRM means don't ask for confirmation at +all. + +Optional third argument PRESERVE-MODES non-nil means don't alter +the files modes. Normally we reinitialize them using `normal-mode'. + +If the value of `revert-buffer-function' is non-nil, it is called to +do the work. + +The default revert function runs the hook `before-revert-hook' at the +beginning and `after-revert-hook' at the end." + ;; I admit it's odd to reverse the sense of the prefix argument, but + ;; there is a lot of code out there which assumes that the first + ;; argument should be t to avoid consulting the auto-save file, and + ;; there's no straightforward way to encourage authors to notice a + ;; reversal of the argument sense. So I'm just changing the user + ;; interface, but leaving the programmatic interface the same. + (interactive (list (not current-prefix-arg))) + (if revert-buffer-function + (funcall revert-buffer-function ignore-auto noconfirm) + (let* ((opoint (point)) + (auto-save-p (and (not ignore-auto) + (recent-auto-save-p) + buffer-auto-save-file-name + (file-readable-p buffer-auto-save-file-name) + (y-or-n-p + "Buffer has been auto-saved recently. Revert from auto-save file? "))) + (file-name (if auto-save-p + buffer-auto-save-file-name + buffer-file-name))) + (cond ((null file-name) + (error "Buffer does not seem to be associated with any file")) + ((or noconfirm + (and (not (buffer-modified-p)) + (let (found) + (dolist (rx revert-without-query found) + (when (string-match rx file-name) + (setq found t))))) + (yes-or-no-p (format "Revert buffer from file %s? " + file-name))) + (run-hooks 'before-revert-hook) + ;; If file was backed up but has changed since, + ;; we shd make another backup. + (and (not auto-save-p) + (not (verify-visited-file-modtime (current-buffer))) + (setq buffer-backed-up nil)) + ;; Get rid of all undo records for this buffer. + (or (eq buffer-undo-list t) + (setq buffer-undo-list nil)) + ;; Effectively copy the after-revert-hook status, + ;; since after-find-file will clobber it. + (let ((global-hook (default-value 'after-revert-hook)) + (local-hook-p (local-variable-p 'after-revert-hook + (current-buffer))) + (local-hook (and (local-variable-p 'after-revert-hook + (current-buffer)) + after-revert-hook))) + (let (buffer-read-only + ;; Don't make undo records for the reversion. + (buffer-undo-list t)) + (if revert-buffer-insert-file-contents-function + (funcall revert-buffer-insert-file-contents-function + file-name auto-save-p) + (if (not (file-exists-p file-name)) + (error "File %s no longer exists!" file-name)) + ;; Bind buffer-file-name to nil + ;; so that we don't try to lock the file. + (let ((buffer-file-name nil)) + (or auto-save-p + (unlock-buffer))) + (widen) + (insert-file-contents file-name (not auto-save-p) + nil nil t))) + (goto-char (min opoint (point-max))) + ;; Recompute the truename in case changes in symlinks + ;; have changed the truename. + ;XEmacs: already done by insert-file-contents + ;;(setq buffer-file-truename + ;;(abbreviate-file-name (file-truename buffer-file-name))) + (after-find-file nil nil t t preserve-modes) + ;; Run after-revert-hook as it was before we reverted. + (setq-default revert-buffer-internal-hook global-hook) + (if local-hook-p + (progn + (make-local-variable 'revert-buffer-internal-hook) + (setq revert-buffer-internal-hook local-hook)) + (kill-local-variable 'revert-buffer-internal-hook)) + (run-hooks 'revert-buffer-internal-hook)) + t))))) + +(defun recover-file (file) + "Visit file FILE, but get contents from its last auto-save file." + ;; Actually putting the file name in the minibuffer should be used + ;; only rarely. + ;; Not just because users often use the default. + (interactive "FRecover file: ") + (setq file (expand-file-name file)) + (let ((handler (or (find-file-name-handler file 'recover-file) + (find-file-name-handler + (let ((buffer-file-name file)) + (make-auto-save-file-name)) + 'recover-file)))) + (if handler + (funcall handler 'recover-file file) + (if (auto-save-file-name-p file) + (error "%s is an auto-save file" file)) + (let ((file-name (let ((buffer-file-name file)) + (make-auto-save-file-name)))) + (cond ((if (file-exists-p file) + (not (file-newer-than-file-p file-name file)) + (not (file-exists-p file-name))) + (error "Auto-save file %s not current" file-name)) + ((save-window-excursion + (if (not (eq system-type 'vax-vms)) + (with-output-to-temp-buffer "*Directory*" + (buffer-disable-undo standard-output) + (call-process "ls" nil standard-output nil + (if (file-symlink-p file) "-lL" "-l") + file file-name))) + (yes-or-no-p (format "Recover auto save file %s? " file-name))) + (switch-to-buffer (find-file-noselect file t)) + (let ((buffer-read-only nil)) + (erase-buffer) + (insert-file-contents file-name nil)) + (after-find-file nil nil t)) + (t (error "Recover-file cancelled."))))))) + +(defun recover-session () + "Recover auto save files from a previous Emacs session. +This command first displays a Dired buffer showing you the +previous sessions that you could recover from. +To choose one, move point to the proper line and then type C-c C-c. +Then you'll be asked about a number of files to recover." + (interactive) + (dired (concat auto-save-list-file-prefix "*")) + (goto-char (point-min)) + (or (looking-at "Move to the session you want to recover,") + (let ((inhibit-read-only t)) + (insert "Move to the session you want to recover,\n" + "then type C-c C-c to select it.\n\n" + "You can also delete some of these files;\n" + "type d on a line to mark that file for deletion.\n\n"))) + (use-local-map (let ((map (make-sparse-keymap))) + (set-keymap-parents map (list (current-local-map))) + map)) + (define-key (current-local-map) "\C-c\C-c" 'recover-session-finish)) + +(defun recover-session-finish () + "Choose one saved session to recover auto-save files from. +This command is used in the special Dired buffer created by +\\[recover-session]." + (interactive) + ;; Get the name of the session file to recover from. + (let ((file (dired-get-filename)) + files + (buffer (get-buffer-create " *recover*"))) + ;; #### dired-do-flagged-delete in FSF. + ;; This version is for ange-ftp + ;;(dired-do-deletions t) + ;; This version is for efs + (dired-expunge-deletions) + (unwind-protect + (save-excursion + ;; Read in the auto-save-list file. + (set-buffer buffer) + (erase-buffer) + (insert-file-contents file) + ;; Loop thru the text of that file + ;; and get out the names of the files to recover. + (while (not (eobp)) + (let (thisfile autofile) + (if (eolp) + ;; This is a pair of lines for a non-file-visiting buffer. + ;; Get the auto-save file name and manufacture + ;; a "visited file name" from that. + (progn + (forward-line 1) + (setq autofile + (buffer-substring-no-properties + (point) + (save-excursion + (end-of-line) + (point)))) + (setq thisfile + (expand-file-name + (substring + (file-name-nondirectory autofile) + 1 -1) + (file-name-directory autofile))) + (forward-line 1)) + ;; This pair of lines is a file-visiting + ;; buffer. Use the visited file name. + (progn + (setq thisfile + (buffer-substring-no-properties + (point) (progn (end-of-line) (point)))) + (forward-line 1) + (setq autofile + (buffer-substring-no-properties + (point) (progn (end-of-line) (point)))) + (forward-line 1))) + ;; Ignore a file if its auto-save file does not exist now. + (if (file-exists-p autofile) + (setq files (cons thisfile files))))) + (setq files (nreverse files)) + ;; The file contains a pair of line for each auto-saved buffer. + ;; The first line of the pair contains the visited file name + ;; or is empty if the buffer was not visiting a file. + ;; The second line is the auto-save file name. + (if files + (map-y-or-n-p "Recover %s? " + (lambda (file) + (condition-case nil + (save-excursion (recover-file file)) + (error + "Failed to recover `%s'" file))) + files + '("file" "files" "recover")) + (message "No files can be recovered from this session now"))) + (kill-buffer buffer)))) + +(defun kill-some-buffers () + "For each buffer, ask whether to kill it." + (interactive) + (let ((list (buffer-list))) + (while list + (let* ((buffer (car list)) + (name (buffer-name buffer))) + (and (not (string-equal name "")) + (/= (aref name 0) ? ) + (yes-or-no-p + (format + (if (buffer-modified-p buffer) + (gettext "Buffer %s HAS BEEN EDITED. Kill? ") + (gettext "Buffer %s is unmodified. Kill? ")) + name)) + (kill-buffer buffer))) + (setq list (cdr list))))) + +(defun auto-save-mode (arg) + "Toggle auto-saving of contents of current buffer. +With prefix argument ARG, turn auto-saving on if positive, else off." + (interactive "P") + (setq buffer-auto-save-file-name + (and (if (null arg) + (or (not buffer-auto-save-file-name) + ;; If autosave is off because buffer has shrunk, + ;; then toggling should turn it on. + (< buffer-saved-size 0)) + (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0)))) + (if (and buffer-file-name auto-save-visited-file-name + (not buffer-read-only)) + buffer-file-name + (make-auto-save-file-name)))) + ;; If -1 was stored here, to temporarily turn off saving, + ;; turn it back on. + (and (< buffer-saved-size 0) + (setq buffer-saved-size 0)) + (if (interactive-p) + (if buffer-auto-save-file-name ;; rewritten for I18N3 snarfing + (display-message 'command "Auto-save on (in this buffer)") + (display-message 'command "Auto-save off (in this buffer)"))) + buffer-auto-save-file-name) + +(defun rename-auto-save-file () + "Adjust current buffer's auto save file name for current conditions. +Also rename any existing auto save file, if it was made in this session." + (let ((osave buffer-auto-save-file-name)) + (setq buffer-auto-save-file-name + (make-auto-save-file-name)) + (if (and osave buffer-auto-save-file-name + (not (string= buffer-auto-save-file-name buffer-file-name)) + (not (string= buffer-auto-save-file-name osave)) + (file-exists-p osave) + (recent-auto-save-p)) + (rename-file osave buffer-auto-save-file-name t)))) + +;; see also ../packages/auto-save.el +(defun make-auto-save-file-name (&optional filename) + "Return file name to use for auto-saves of current buffer. +Does not consider `auto-save-visited-file-name' as that variable is checked +before calling this function. You can redefine this for customization. +See also `auto-save-file-name-p'." + (let ((fname (or filename buffer-file-name)) + name) + (setq name + (if fname + (concat (file-name-directory fname) + "#" + (file-name-nondirectory fname) + "#") + + ;; Deal with buffers that don't have any associated files. (Mail + ;; mode tends to create a good number of these.) + + (let ((buffer-name (buffer-name)) + (limit 0)) + ;; Use technique from Sebastian Kremer's auto-save + ;; package to turn slashes into \\!. This ensures that + ;; the auto-save buffer name is unique. + + ;; #### - yuck! yuck! yuck! move this functionality + ;; somewhere else and make the name translation customizable. + ;; Using "\!" as part of a filename on a UNIX filesystem is nearly + ;; IMPOSSIBLE to get past a shell parser. -stig + + (while (string-match "[/\\]" buffer-name limit) + (setq buffer-name + (concat (substring buffer-name 0 (match-beginning 0)) + (if (string= (substring buffer-name + (match-beginning 0) + (match-end 0)) + "/") + "\\!" + "\\\\") + (substring buffer-name (match-end 0)))) + (setq limit (1+ (match-end 0)))) + + ;; (expand-file-name (format "#%s#%s#" (buffer-name) (make-temp-name ""))) + + ;; jwz: putting the emacs PID in the auto-save file name + ;; is bad news, because that defeats auto-save-recovery of + ;; *mail* buffers -- the (sensible) code in sendmail.el + ;; calls (make-auto-save-file-name) to determine whether + ;; there is unsent, auto-saved mail to recover. If that + ;; mail came from a previous emacs process (far and away + ;; the most likely case) then this can never succeed as + ;; the pid differs. + + (expand-file-name (format "#%s#" buffer-name))) + )) + ;; don't try to write auto-save files in unwritable places. Unless + ;; there's already an autosave file here, put ours somewhere safe. --Stig + (if (or (file-writable-p name) + (file-exists-p name)) + name + (expand-file-name (concat "~/" (file-name-nondirectory name)))))) + +(defun auto-save-file-name-p (filename) + "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'. +FILENAME should lack slashes. +You can redefine this for customization." + (string-match "\\`#.*#\\'" filename)) + +(defcustom list-directory-brief-switches + (if (eq system-type 'vax-vms) "" "-CF") + "*Switches for list-directory to pass to `ls' for brief listing." + :type 'string + :group 'dired) + +(defcustom list-directory-verbose-switches + (if (eq system-type 'vax-vms) + "/PROTECTION/SIZE/DATE/OWNER/WIDTH=(OWNER:10)" + "-l") + "*Switches for list-directory to pass to `ls' for verbose listing," + :type 'string + :group 'dired) + +(defun list-directory (dirname &optional verbose) + "Display a list of files in or matching DIRNAME, a la `ls'. +DIRNAME is globbed by the shell if necessary. +Prefix arg (second arg if noninteractive) means supply -l switch to `ls'. +Actions controlled by variables `list-directory-brief-switches' +and `list-directory-verbose-switches'." + (interactive (let ((pfx current-prefix-arg)) + (list (read-file-name (if pfx (gettext "List directory (verbose): ") + (gettext "List directory (brief): ")) + nil default-directory nil) + pfx))) + (let ((switches (if verbose list-directory-verbose-switches + list-directory-brief-switches))) + (or dirname (setq dirname default-directory)) + (setq dirname (expand-file-name dirname)) + (with-output-to-temp-buffer "*Directory*" + (buffer-disable-undo standard-output) + (princ "Directory ") + (princ dirname) + (terpri) + (save-excursion + (set-buffer "*Directory*") + (setq default-directory (file-name-directory dirname)) + (let ((wildcard (not (file-directory-p dirname)))) + (insert-directory dirname switches wildcard (not wildcard))))))) + +(defvar insert-directory-program "ls" + "Absolute or relative name of the `ls' program used by `insert-directory'.") + +;; insert-directory +;; - must insert _exactly_one_line_ describing FILE if WILDCARD and +;; FULL-DIRECTORY-P is nil. +;; The single line of output must display FILE's name as it was +;; given, namely, an absolute path name. +;; - must insert exactly one line for each file if WILDCARD or +;; FULL-DIRECTORY-P is t, plus one optional "total" line +;; before the file lines, plus optional text after the file lines. +;; Lines are delimited by "\n", so filenames containing "\n" are not +;; allowed. +;; File lines should display the basename. +;; - must be consistent with +;; - functions dired-move-to-filename, (these two define what a file line is) +;; dired-move-to-end-of-filename, +;; dired-between-files, (shortcut for (not (dired-move-to-filename))) +;; dired-insert-headerline +;; dired-after-subdir-garbage (defines what a "total" line is) +;; - variable dired-subdir-regexp +(defun insert-directory (file switches &optional wildcard full-directory-p) + "Insert directory listing for FILE, formatted according to SWITCHES. +Leaves point after the inserted text. +SWITCHES may be a string of options, or a list of strings. +Optional third arg WILDCARD means treat FILE as shell wildcard. +Optional fourth arg FULL-DIRECTORY-P means file is a directory and +switches do not contain `d', so that a full listing is expected. + +This works by running a directory listing program +whose name is in the variable `insert-directory-program'. +If WILDCARD, it also runs the shell specified by `shell-file-name'." + ;; We need the directory in order to find the right handler. + (let ((handler (find-file-name-handler (expand-file-name file) + 'insert-directory))) + (if handler + (funcall handler 'insert-directory file switches + wildcard full-directory-p) + (if (eq system-type 'vax-vms) + (vms-read-directory file switches (current-buffer)) + (if wildcard + ;; Run ls in the directory of the file pattern we asked for. + (let ((default-directory + (if (file-name-absolute-p file) + (file-name-directory file) + (file-name-directory (expand-file-name file)))) + (pattern (file-name-nondirectory file)) + (beg 0)) + ;; Quote some characters that have special meanings in shells; + ;; but don't quote the wildcards--we want them to be special. + ;; We also currently don't quote the quoting characters + ;; in case people want to use them explicitly to quote + ;; wildcard characters. + ;;#### Unix-specific + (while (string-match "[ \t\n;<>&|()#$]" pattern beg) + (setq pattern + (concat (substring pattern 0 (match-beginning 0)) + "\\" + (substring pattern (match-beginning 0))) + beg (1+ (match-end 0)))) + (call-process shell-file-name nil t nil + "-c" (concat "\\" ;; Disregard shell aliases! + insert-directory-program + " -d " + (if (stringp switches) + switches + (mapconcat 'identity switches " ")) + " " + pattern))) + ;; SunOS 4.1.3, SVr4 and others need the "." to list the + ;; directory if FILE is a symbolic link. + (apply 'call-process + insert-directory-program nil t nil + (let (list) + (if (listp switches) + (setq list switches) + (if (not (equal switches "")) + (progn + ;; Split the switches at any spaces + ;; so we can pass separate options as separate args. + (while (string-match " " switches) + (setq list (cons (substring switches 0 (match-beginning 0)) + list) + switches (substring switches (match-end 0)))) + (setq list (cons switches list))))) + (append list + (list + (if full-directory-p + (concat (file-name-as-directory file) + ;;#### Unix-specific + ".") + file)))))))))) + +(defvar kill-emacs-query-functions nil + "Functions to call with no arguments to query about killing XEmacs. +If any of these functions returns nil, killing Emacs is cancelled. +`save-buffers-kill-emacs' (\\[save-buffers-kill-emacs]) calls these functions, +but `kill-emacs', the low level primitive, does not. +See also `kill-emacs-hook'.") + +(defun save-buffers-kill-emacs (&optional arg) + "Offer to save each buffer, then kill this XEmacs process. +With prefix arg, silently save all file-visiting buffers, then kill." + (interactive "P") + (save-some-buffers arg t) + (and (or (not (memq t (mapcar #'(lambda (buf) (and (buffer-file-name buf) + (buffer-modified-p buf))) + (buffer-list)))) + (yes-or-no-p "Modified buffers exist; exit anyway? ")) + (or (not (fboundp 'process-list)) + ;; process-list is not defined on VMS. + (let ((processes (process-list)) + active) + (while processes + (and (memq (process-status (car processes)) '(run stop open)) + (let ((val (process-kill-without-query (car processes)))) + (process-kill-without-query (car processes) val) + val) + (setq active t)) + (setq processes (cdr processes))) + (or + (not active) + (save-excursion + (save-window-excursion + (delete-other-windows) + (list-processes) + (yes-or-no-p + "Active processes exist; kill them and exit anyway? ")))))) + ;; Query the user for other things, perhaps. + (run-hook-with-args-until-failure 'kill-emacs-query-functions) + (kill-emacs))) + +(defun symlink-expand-file-name (filename) + "If FILENAME is a symlink, return its non-symlink equivalent. +Unlike `file-truename', this doesn't chase symlinks in directory +components of the file or expand a relative pathname into an +absolute one." + (let ((count 20)) + (while (and (> count 0) (file-symlink-p filename)) + (setq filename (file-symlink-p filename) + count (1- count))) + (if (> count 0) + filename + (error "Apparently circular symlink path")))) + +;; Suggested by Michael Kifer +(defun file-remote-p (file-name) + "Test whether FILE-NAME is looked for on a remote system." + (cond ((not allow-remote-paths) nil) + ((featurep 'ange-ftp) (ange-ftp-ftp-path file-name)) + (t (efs-ftp-path file-name)))) + +;;; files.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/fill.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/fill.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,1061 @@ +;;; fill.el --- fill commands for XEmacs. + +;; Copyright (C) 1985, 86, 92, 94, 95, 1997 Free Software Foundation, Inc. + +;; Maintainer: XEmacs Development Team +;; Keywords: wp, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; All the commands for filling text. These are documented in the XEmacs +;; Reference Manual. + +;; 97/3/14 Jareth Hein (jhod@po.iijnet.or.jp) added functions for kinsoku (asian text +;; line break processing) +;; 97/06/11 Steve Baur (steve@altair.xemacs.org) converted broken +;; following-char/preceding-char calls to char-after/char-before. + +;;; Code: + +(defconst fill-individual-varying-indent nil + "*Controls criterion for a new paragraph in `fill-individual-paragraphs'. +Non-nil means changing indent doesn't end a paragraph. +That mode can handle paragraphs with extra indentation on the first line, +but it requires separator lines between paragraphs. +A value of nil means that any change in indentation starts a new paragraph.") + +(defconst sentence-end-double-space t + "*Non-nil means a single space does not end a sentence. +This variable applies only to filling, not motion commands. To +change the behavior of motion commands, see `sentence-end'.") + +(defconst colon-double-space nil + "*Non-nil means put two spaces after a colon when filling.") + +(defvar fill-paragraph-function nil + "Mode-specific function to fill a paragraph, or nil if there is none. +If the function returns nil, then `fill-paragraph' does its normal work.") + +(defun set-fill-prefix () + "Set the fill prefix to the current line up to point. +Filling expects lines to start with the fill prefix and +reinserts the fill prefix in each resulting line." + (interactive) + (setq fill-prefix (buffer-substring + (save-excursion (move-to-left-margin) (point)) + (point))) + (if (equal fill-prefix "") + (setq fill-prefix nil)) + (if fill-prefix + (message "fill-prefix: \"%s\"" fill-prefix) + (message "fill-prefix cancelled"))) + +(defconst adaptive-fill-mode t + "*Non-nil means determine a paragraph's fill prefix from its text.") + +;; #### - this is still weak. Yeah, there's filladapt, but this should +;; still be better... --Stig +(defconst adaptive-fill-regexp (purecopy "[ \t]*\\([#;>*]+ +\\)?") + "*Regexp to match text at start of line that constitutes indentation. +If Adaptive Fill mode is enabled, whatever text matches this pattern +on the second line of a paragraph is used as the standard indentation +for the paragraph. If the paragraph has just one line, the indentation +is taken from that line.") + +(defvar adaptive-fill-function nil + "*Function to call to choose a fill prefix for a paragraph. +This function is used when `adaptive-fill-regexp' does not match.") + +;; Added for kinsoku processing. Use this instead of +;; (skip-chars-backward "^ \t\n") +;; (skip-chars-backward "^ \n" linebeg) +(defun fill-move-backward-to-break-point (regexp &optional lim) + (let ((opoint (point))) + ;; 93.8.23 by kawamoto@ics.es.osaka-u.ac.jp + ;; case of first 'word' being longer than fill-column + (if (not (re-search-backward regexp lim 'move)) + nil + ;; we have skipped backward SPC or WAN (word-across-newline). So move point forward again. + (forward-char) + (if (< opoint (point)) + (forward-char -1))))) + +;; Added for kinsoku processing. Use instead of +;; (re-search-forward "[ \t]" opoint t) +;; (skip-chars-forward "^ \n") +;; (skip-chars-forward "^ \n") +(defun fill-move-forward-to-break-point (regexp &optional lim) + (let ((opoint (point))) + (if (not (re-search-forward regexp lim 'move)) + nil + (forward-char -1) + (if (< (point) opoint) + (forward-char)))) + (if (featurep 'mule) (kinsoku-process-extend))) + +(defun fill-end-of-sentence-p () + (save-excursion + (skip-chars-backward " ]})\"'") + (memq (char-before (point)) '(?. ?? ?!)))) + +(defun current-fill-column () + "Return the fill-column to use for this line. +The fill-column to use for a buffer is stored in the variable `fill-column', +but can be locally modified by the `right-margin' text property, which is +subtracted from `fill-column'. + +The fill column to use for a line is the first column at which the column +number equals or exceeds the local fill-column - right-margin difference." + (save-excursion + (if fill-column + (let* ((here (progn (beginning-of-line) (point))) + (here-col 0) + (eol (progn (end-of-line) (point))) + margin fill-col change col) + ;; Look separately at each region of line with a different right-margin. + (while (and (setq margin (get-text-property here 'right-margin) + fill-col (- fill-column (or margin 0)) + change (text-property-not-all + here eol 'right-margin margin)) + (progn (goto-char (1- change)) + (setq col (current-column)) + (< col fill-col))) + (setq here change + here-col col)) + (max here-col fill-col))))) + +(defun canonically-space-region (beg end) + "Remove extra spaces between words in region. +Leave one space between words, two at end of sentences or after colons +\(depending on values of `sentence-end-double-space' and `colon-double-space'). +Remove indentation from each line." + (interactive "r") + ;;;### 97/3/14 jhod: Do I have to add anything here for kinsoku? + (save-excursion + (goto-char beg) + ;; XEmacs - (ENE/stig from fa-extras.el): Skip the start of a comment. + (and comment-start-skip + (looking-at comment-start-skip) + (goto-char (match-end 0))) + ;; Nuke tabs; they get screwed up in a fill. + ;; This is quick, but loses when a tab follows the end of a sentence. + ;; Actually, it is difficult to tell that from "Mr.\tSmith". + ;; Blame the typist. + (subst-char-in-region beg end ?\t ?\ ) + (while (and (< (point) end) + (re-search-forward " *" end t)) + (delete-region + (+ (match-beginning 0) + ;; Determine number of spaces to leave: + (save-excursion + (skip-chars-backward " ]})\"'") + (cond ((and sentence-end-double-space + (memq (char-before (point)) '(?. ?? ?!))) 2) + ((and colon-double-space + (eq (char-before (point)) ?:)) 2) + ((char-equal (char-before (point)) ?\n) 0) + (t 1)))) + (match-end 0))) + ;; Make sure sentences ending at end of line get an extra space. + ;; loses on split abbrevs ("Mr.\nSmith") + (goto-char beg) + (while (and (< (point) end) + (re-search-forward "[.?!][])}\"']*$" end t)) + ;; We insert before markers in case a caller such as + ;; do-auto-fill has done a save-excursion with point at the end + ;; of the line and wants it to stay at the end of the line. + (insert ? )))) +;; XEmacs: we don't have this function. +;; (insert-before-markers-and-inherit ? )))) + +;; XEmacs -- added DONT-SKIP-FIRST. Port of older code changes by Stig. +;; #### probably this junk is broken -- do-auto-fill doesn't actually use +;; it. If so, it should be removed. + +(defun fill-context-prefix (from to &optional first-line-regexp + dont-skip-first) + "Compute a fill prefix from the text between FROM and TO. +This uses the variables `adaptive-fill-prefix' and `adaptive-fill-function'. +If FIRST-LINE-REGEXP is non-nil, then when taking a prefix from the +first line, insist it must match FIRST-LINE-REGEXP." + (save-excursion + (goto-char from) + (if (eolp) (forward-line 1)) + ;; Move to the second line unless there is just one. + (let ((firstline (point)) + ;; Non-nil if we are on the second line. + at-second + result) + ;; XEmacs change + (if (not dont-skip-first) + (forward-line 1)) + (if (>= (point) to) + (goto-char firstline) + (setq at-second t)) + (move-to-left-margin) + ;; XEmacs change + (let ((start (point)) + ; jhod: no longer used? + ;(eol (save-excursion (end-of-line) (point))) + ) + (setq result + (if (not (looking-at paragraph-start)) + (cond ((and adaptive-fill-regexp (looking-at adaptive-fill-regexp)) + (buffer-substring-no-properties start (match-end 0))) + (adaptive-fill-function (funcall adaptive-fill-function))))) + (and result + (or at-second + (null first-line-regexp) + (string-match first-line-regexp result)) + result))))) + +;; XEmacs (stig) - this is pulled out of fill-region-as-paragraph so that it +;; can also be called from do-auto-fill +;; #### But it's not used there. Chuck pulled it out because it broke things. +(defun maybe-adapt-fill-prefix (&optional from to dont-skip-first) + (if (and adaptive-fill-mode + (or (null fill-prefix) (string= fill-prefix ""))) + (setq fill-prefix (fill-context-prefix from to nil dont-skip-first)))) + +(defun fill-region-as-paragraph (from to &optional justify + nosqueeze squeeze-after) + "Fill the region as one paragraph. +It removes any paragraph breaks in the region and extra newlines at the end, +indents and fills lines between the margins given by the +`current-left-margin' and `current-fill-column' functions. +It leaves point at the beginning of the line following the paragraph. + +Normally performs justification according to the `current-justification' +function, but with a prefix arg, does full justification instead. + +From a program, optional third arg JUSTIFY can specify any type of +justification. Fourth arg NOSQUEEZE non-nil means not to make spaces +between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil, +means don't canonicalize spaces before that position. + +If `sentence-end-double-space' is non-nil, then period followed by one +space does not end a sentence, so don't break a line there." + (interactive + (progn + ;; XEmacs addition: + (barf-if-buffer-read-only nil (region-beginning) (region-end)) + (list (region-beginning) (region-end) + (if current-prefix-arg 'full)))) + ;; Arrange for undoing the fill to restore point. + (if (and buffer-undo-list (not (eq buffer-undo-list t))) + (setq buffer-undo-list (cons (point) buffer-undo-list))) + + ;; Make sure "to" is the endpoint. + (goto-char (min from to)) + (setq to (max from to)) + ;; Ignore blank lines at beginning of region. + (skip-chars-forward " \t\n") + + (let ((from-plus-indent (point)) + (oneleft nil)) + + (beginning-of-line) + (setq from (point)) + + ;; Delete all but one soft newline at end of region. + ;; And leave TO before that one. + (goto-char to) + (while (and (> (point) from) (eq ?\n (char-after (1- (point))))) + (if (and oneleft + (not (and use-hard-newlines + (get-text-property (1- (point)) 'hard)))) + (delete-backward-char 1) + (backward-char 1) + (setq oneleft t))) + (setq to (point)) + + ;; If there was no newline, and there is text in the paragraph, then + ;; create a newline. + (if (and (not oneleft) (> to from-plus-indent)) + (newline)) + (goto-char from-plus-indent)) + + (if (not (> to (point))) + nil ; There is no paragraph, only whitespace: exit now. + + (or justify (setq justify (current-justification))) + + ;; Don't let Adaptive Fill mode alter the fill prefix permanently. + (let ((fill-prefix fill-prefix)) + ;; Figure out how this paragraph is indented, if desired. + ;; XEmacs: move some code here to a separate function. + (maybe-adapt-fill-prefix from to t) + + (save-restriction + (goto-char from) + (beginning-of-line) + (narrow-to-region (point) to) + + (if (not justify) ; filling disabled: just check indentation + (progn + (goto-char from) + (while (not (eobp)) + (if (and (not (eolp)) + (< (current-indentation) (current-left-margin))) + (indent-to-left-margin)) + (forward-line 1))) + + (if use-hard-newlines + (remove-text-properties from (point-max) '(hard nil))) + ;; Make sure first line is indented (at least) to left margin... + (if (or (memq justify '(right center)) + (< (current-indentation) (current-left-margin))) + (indent-to-left-margin)) + ;; Delete the fill prefix from every line except the first. + ;; The first line may not even have a fill prefix. + (goto-char from) + (let ((fpre (and fill-prefix (not (equal fill-prefix "")) + (concat "[ \t]*" + (regexp-quote fill-prefix) + "[ \t]*")))) + (and fpre + (progn + (if (>= (+ (current-left-margin) (length fill-prefix)) + (current-fill-column)) + (error "fill-prefix too long for specified width")) + (goto-char from) + (forward-line 1) + (while (not (eobp)) + (if (looking-at fpre) + (delete-region (point) (match-end 0))) + (forward-line 1)) + (goto-char from) + (if (looking-at fpre) + (goto-char (match-end 0))) + (setq from (point))))) + ;; Remove indentation from lines other than the first. + (beginning-of-line 2) + (indent-region (point) (point-max) 0) + (goto-char from) + + ;; FROM, and point, are now before the text to fill, + ;; but after any fill prefix on the first line. + + ;; Make sure sentences ending at end of line get an extra space. + ;; loses on split abbrevs ("Mr.\nSmith") + (while (re-search-forward "[.?!][])}\"']*$" nil t) + ;; XEmacs change (no insert-and-inherit) + (or (eobp) (insert ?\ ?\ ))) + (goto-char from) + (skip-chars-forward " \t") + ;; Then change all newlines to spaces. + ;;; 97/3/14 jhod: Kinsoku change + ;; Spacing is not necessary for charcters of no word-separater. + ;; The regexp word-across-newline is used for this check. + (if (not (and (featurep 'mule) + (stringp word-across-newline))) + (subst-char-in-region from (point-max) ?\n ?\ ) + ;; + ;; WAN +NL+WAN --> WAN + WAN + ;; not(WAN)+NL+WAN --> not(WAN) + WAN + ;; WAN +NL+not(WAN) --> WAN + not(WAN) + ;; SPC +NL+not(WAN) --> SPC + not(WAN) + ;; not(WAN)+NL+not(WAN) --> not(WAN) + SPC + not(WAN) + ;; + (goto-char from) + (end-of-line) + (while (not (eobp)) + ;; Insert SPC only when point is between nonWAN. Insert + ;; before deleting to preserve marker if possible. + (if (or (prog2 ; check following char. + (forward-char) ; skip newline + (or (eobp) + (looking-at word-across-newline)) + (forward-char -1)) + (prog2 ; check previous char. + (forward-char -1) + (or (eq (char-after (point)) ?\ ) + (looking-at word-across-newline)) + (forward-char))) + nil + (insert ?\ )) + (delete-char 1) ; delete newline + (end-of-line))) + ;; end patch + (goto-char from) + (skip-chars-forward " \t") + (if (and nosqueeze (not (eq justify 'full))) + nil + (canonically-space-region (or squeeze-after (point)) (point-max)) + (goto-char (point-max)) + (delete-horizontal-space) + ;; XEmacs change (no insert-and-inherit) + (insert " ")) + (goto-char (point-min)) + + ;; This is the actual filling loop. + (let ((prefixcol 0) linebeg + (re-break-point (if (featurep 'mule) + (concat "[ \n\t]\\|" word-across-newline) + "[ \n\t]"))) + (while (not (eobp)) + (setq linebeg (point)) + (move-to-column (1+ (current-fill-column))) + (if (eobp) + (or nosqueeze (delete-horizontal-space)) + ;; Move back to start of word. + ;; 97/3/14 jhod: Kinsoku + ;(skip-chars-backward "^ \n" linebeg) + (fill-move-backward-to-break-point re-break-point linebeg) + ;; end patch + ;; Don't break after a period followed by just one space. + ;; Move back to the previous place to break. + ;; The reason is that if a period ends up at the end of a line, + ;; further fills will assume it ends a sentence. + ;; If we now know it does not end a sentence, + ;; avoid putting it at the end of the line. + (if sentence-end-double-space + (while (and (> (point) (+ linebeg 2)) + (eq (char-before (point)) ?\ ) + (not (eq (char-after (point)) ?\ )) + (eq (char-after (- (point) 2)) ?\.)) + (forward-char -2) + ;; 97/3/14 jhod: Kinsoku + ;(skip-chars-backward "^ \n" linebeg))) + (fill-move-backward-to-break-point re-break-point linebeg))) + (if (featurep 'mule) (kinsoku-process)) + ;end patch + + ;; If the left margin and fill prefix by themselves + ;; pass the fill-column. or if they are zero + ;; but we have no room for even one word, + ;; keep at least one word anyway. + ;; This handles ALL BUT the first line of the paragraph. + (if (if (zerop prefixcol) + (save-excursion + (skip-chars-backward " \t" linebeg) + (bolp)) + (>= prefixcol (current-column))) + ;; Ok, skip at least one word. + ;; Meanwhile, don't stop at a period followed by one space. + (let ((first t)) + (move-to-column prefixcol) + (while (and (not (eobp)) + (or first + (and (not (bobp)) + sentence-end-double-space + (save-excursion (forward-char -1) + (and (looking-at "\\. ") + (not (looking-at "\\. "))))))) + (skip-chars-forward " \t") + ;; 94/3/14 jhod: Kinsoku + ;(skip-chars-forward "^ \n\t") + (fill-move-forward-to-break-point re-break-point) + ;; end patch + (setq first nil))) + ;; Normally, move back over the single space between the words. + (if (eq (char-before (point)) ?\ ) + (forward-char -1))) + ;; If the left margin and fill prefix by themselves + ;; pass the fill-column, keep at least one word. + ;; This handles the first line of the paragraph. + (if (and (zerop prefixcol) + (let ((fill-point (point)) nchars) + (save-excursion + (move-to-left-margin) + (setq nchars (- fill-point (point))) + (or (< nchars 0) + (and fill-prefix + (< nchars (length fill-prefix)) + (string= (buffer-substring (point) fill-point) + (substring fill-prefix 0 nchars))))))) + ;; Ok, skip at least one word. But + ;; don't stop at a period followed by just one space. + (let ((first t)) + (while (and (not (eobp)) + (or first + (and (not (bobp)) + sentence-end-double-space + (save-excursion (forward-char -1) + (and (looking-at "\\. ") + (not (looking-at "\\. "))))))) + (skip-chars-forward " \t") + ;; 97/3/14 jhod: Kinsoku + ;(skip-chars-forward "^ \t\n") + (fill-move-forward-to-break-point re-break-point) + ;; end patch + (setq first nil)))) + ;; Check again to see if we got to the end of the paragraph. + (if (save-excursion (skip-chars-forward " \t") (eobp)) + (or nosqueeze (delete-horizontal-space)) + ;; Replace whitespace here with one newline, then indent to left + ;; margin. + (skip-chars-backward " \t") + ;; 97/3/14 jhod: More kinsoku stuff + (if (featurep 'mule) + ;; WAN means chars which match word-across-newline. + ;; (0) | SPC + SPC* --> NL + ;; (1) WAN | SPC + SPC* --> WAN + SPC + NL + ;; (2) | SPC + SPC* + WAN --> SPC + NL + WAN + ;; (3) '.' | SPC + nonSPC --> '.' + SPC + NL + nonSPC + ;; (4) '.' | SPC + SPC --> '.' + NL + ;; (5) | SPC* --> NL + (let ((start (point)) ; 92.6.30 by K.Handa + (ch (char-after (point)))) + (if (and (= ch ? ) + (progn ; not case (0) -- 92.6.30 by K.Handa + (skip-chars-forward " \t") + (not (eobp))) + (or + (progn ; case (1) + (goto-char start) + (forward-char -1) + (looking-at word-across-newline)) + (progn ; case (2) + (goto-char start) + (skip-chars-forward " \t") + (and (not (eobp)) + (looking-at word-across-newline) + ;; never leave space after the end of sentence + (not (fill-end-of-sentence-p)))) + (progn ; case (3) + (goto-char (1+ start)) + (and (not (eobp)) + (not (eq (char-after (point)) ? )) + (fill-end-of-sentence-p))))) + ;; We should keep one SPACE before NEWLINE. (1),(2),(3) + (goto-char (1+ start)) + ;; We should delete all SPACES around break point. (4),(5) + (goto-char start)))) + ;; end of patch + (insert ?\n) + ;; Give newline the properties of the space(s) it replaces + (set-text-properties (1- (point)) (point) + (text-properties-at (point))) + (indent-to-left-margin) + ;; Insert the fill prefix after indentation. + ;; Set prefixcol so whitespace in the prefix won't get lost. + (and fill-prefix (not (equal fill-prefix "")) + (progn + (insert fill-prefix) + (setq prefixcol (current-column)))))) + ;; Justify the line just ended, if desired. + (if justify + (if (save-excursion (skip-chars-forward " \t") (eobp)) + (progn + (delete-horizontal-space) + (justify-current-line justify t t)) + (forward-line -1) + (justify-current-line justify nil t) + (forward-line 1)))))) + ;; Leave point after final newline. + (goto-char (point-max))) + (forward-char 1)))) + +(defun fill-paragraph (arg) + "Fill paragraph at or after point. Prefix arg means justify as well. +If `sentence-end-double-space' is non-nil, then period followed by one +space does not end a sentence, so don't break a line there. + +If `fill-paragraph-function' is non-nil, we call it (passing our +argument to it), and if it returns non-nil, we simply return its value." + (interactive (list (if current-prefix-arg 'full))) + (or (and fill-paragraph-function + (let ((function fill-paragraph-function) + fill-paragraph-function) + (funcall function arg))) + (let ((before (point))) + (save-excursion + (forward-paragraph) + (or (bolp) (newline 1)) + (let ((end (point)) + (beg (progn (backward-paragraph) (point)))) + (goto-char before) + (if use-hard-newlines + ;; Can't use fill-region-as-paragraph, since this paragraph may + ;; still contain hard newlines. See fill-region. + (fill-region beg end arg) + (fill-region-as-paragraph beg end arg))))))) + +(defun fill-region (from to &optional justify nosqueeze to-eop) + "Fill each of the paragraphs in the region. +Prefix arg (non-nil third arg, if called from program) means justify as well. + +Noninteractively, fourth arg NOSQUEEZE non-nil means to leave +whitespace other than line breaks untouched, and fifth arg TO-EOP +non-nil means to keep filling to the end of the paragraph (or next +hard newline, if `use-hard-newlines' is on). + +If `sentence-end-double-space' is non-nil, then period followed by one +space does not end a sentence, so don't break a line there." + (interactive + (progn + ;; XEmacs addition: + (barf-if-buffer-read-only nil (region-beginning) (region-end)) + (list (region-beginning) (region-end) + (if current-prefix-arg 'full)))) + (let (end beg) + (save-restriction + (goto-char (max from to)) + (if to-eop + (progn (skip-chars-backward "\n") + (forward-paragraph))) + (setq end (point)) + (goto-char (setq beg (min from to))) + (beginning-of-line) + (narrow-to-region (point) end) + (while (not (eobp)) + (let ((initial (point)) + end) + ;; If using hard newlines, break at every one for filling + ;; purposes rather than using paragraph breaks. + (if use-hard-newlines + (progn + (while (and (setq end (text-property-any (point) (point-max) + 'hard t)) + (not (eq ?\n (char-after end))) + (not (= end (point-max)))) + (goto-char (1+ end))) + (setq end (if end (min (point-max) (1+ end)) (point-max))) + (goto-char initial)) + (forward-paragraph 1) + (setq end (point)) + (forward-paragraph -1)) + (if (< (point) beg) + (goto-char beg)) + (if (>= (point) initial) + (fill-region-as-paragraph (point) end justify nosqueeze) + (goto-char end))))))) + +;; XEmacs addition: from Tim Bradshaw +(defun fill-paragraph-or-region (arg) + "Fill the current region, if it's active; otherwise, fill the paragraph. +See `fill-paragraph' and `fill-region' for more information." + (interactive "*P") + (if (region-active-p) + (fill-region (point) (mark) arg) + (fill-paragraph arg))) + + +(defconst default-justification 'left + "*Method of justifying text not otherwise specified. +Possible values are `left', `right', `full', `center', or `none'. +The requested kind of justification is done whenever lines are filled. +The `justification' text-property can locally override this variable. +This variable automatically becomes buffer-local when set in any fashion.") +(make-variable-buffer-local 'default-justification) + +(defun current-justification () + "How should we justify this line? +This returns the value of the text-property `justification', +or the variable `default-justification' if there is no text-property. +However, it returns nil rather than `none' to mean \"don't justify\"." + (let ((j (or (get-text-property + ;; Make sure we're looking at paragraph body. + (save-excursion (skip-chars-forward " \t") + (if (and (eobp) (not (bobp))) + (1- (point)) (point))) + 'justification) + default-justification))) + (if (eq 'none j) + nil + j))) + +(defun set-justification (begin end value &optional whole-par) + "Set the region's justification style. +The kind of justification to use is prompted for. +If the mark is not active, this command operates on the current paragraph. +If the mark is active, the region is used. However, if the beginning and end +of the region are not at paragraph breaks, they are moved to the beginning and +end of the paragraphs they are in. +If `use-hard-newlines' is true, all hard newlines are taken to be paragraph +breaks. + +When calling from a program, operates just on region between BEGIN and END, +unless optional fourth arg WHOLE-PAR is non-nil. In that case bounds are +extended to include entire paragraphs as in the interactive command." + ;; XEmacs change (was mark-active) + (interactive (list (if (region-active-p) (region-beginning) (point)) + (if (region-active-p) (region-end) (point)) + (let ((s (completing-read + "Set justification to: " + '(("left") ("right") ("full") + ("center") ("none")) + nil t))) + (if (equal s "") (error "")) + (intern s)) + t)) + (save-excursion + (save-restriction + (if whole-par + (let ((paragraph-start (if use-hard-newlines "." paragraph-start)) + (paragraph-ignore-fill-prefix (if use-hard-newlines t + paragraph-ignore-fill-prefix))) + (goto-char begin) + (while (and (bolp) (not (eobp))) (forward-char 1)) + (backward-paragraph) + (setq begin (point)) + (goto-char end) + (skip-chars-backward " \t\n" begin) + (forward-paragraph) + (setq end (point)))) + + (narrow-to-region (point-min) end) + (unjustify-region begin (point-max)) + (put-text-property begin (point-max) 'justification value) + (fill-region begin (point-max) nil t)))) + +(defun set-justification-none (b e) + "Disable automatic filling for paragraphs in the region. +If the mark is not active, this applies to the current paragraph." + ;; XEmacs change (was mark-active) + (interactive (list (if (region-active-p) (region-beginning) (point)) + (if (region-active-p) (region-end) (point)))) + (set-justification b e 'none t)) + +(defun set-justification-left (b e) + "Make paragraphs in the region left-justified. +This is usually the default, but see the variable `default-justification'. +If the mark is not active, this applies to the current paragraph." + ;; XEmacs change (was mark-active) + (interactive (list (if (region-active-p) (region-beginning) (point)) + (if (region-active-p) (region-end) (point)))) + (set-justification b e 'left t)) + +(defun set-justification-right (b e) + "Make paragraphs in the region right-justified: +Flush at the right margin and ragged on the left. +If the mark is not active, this applies to the current paragraph." + ;; XEmacs change (was mark-active) + (interactive (list (if (region-active-p) (region-beginning) (point)) + (if (region-active-p) (region-end) (point)))) + (set-justification b e 'right t)) + +(defun set-justification-full (b e) + "Make paragraphs in the region fully justified: +This makes lines flush on both margins by inserting spaces between words. +If the mark is not active, this applies to the current paragraph." + ;; XEmacs change (was mark-active) + (interactive (list (if (region-active-p) (region-beginning) (point)) + (if (region-active-p) (region-end) (point)))) + (set-justification b e 'full t)) + +(defun set-justification-center (b e) + "Make paragraphs in the region centered. +If the mark is not active, this applies to the current paragraph." + ;; XEmacs change (was mark-active) + (interactive (list (if (region-active-p) (region-beginning) (point)) + (if (region-active-p) (region-end) (point)))) + (set-justification b e 'center t)) + +;; 97/3/14 jhod: This functions are added for Kinsoku support +(defun find-space-insertable-point () + "Search backward for a permissable point for inserting justification spaces" + (if (boundp 'space-insertable) + (if (re-search-backward space-insertable nil t) + (progn (forward-char 1) + t) + nil) + (search-backward " " nil t))) + +;; A line has up to six parts: +;; +;; >>> hello. +;; [Indent-1][FP][ Indent-2 ][text][trailing whitespace][newline] +;; +;; "Indent-1" is the left-margin indentation; normally it ends at column +;; given by the `current-left-margin' function. +;; "FP" is the fill-prefix. It can be any string, including whitespace. +;; "Indent-2" is added to justify a line if the `current-justification' is +;; `center' or `right'. In `left' and `full' justification regions, any +;; whitespace there is part of the line's text, and should not be changed. +;; Trailing whitespace is not counted as part of the line length when +;; center- or right-justifying. +;; +;; All parts of the line are optional, although the final newline can +;; only be missing on the last line of the buffer. + +(defun justify-current-line (&optional how eop nosqueeze) + "Do some kind of justification on this line. +Normally does full justification: adds spaces to the line to make it end at +the column given by `current-fill-column'. +Optional first argument HOW specifies alternate type of justification: +it can be `left', `right', `full', `center', or `none'. +If HOW is t, will justify however the `current-justification' function says to. +If HOW is nil or missing, full justification is done by default. +Second arg EOP non-nil means that this is the last line of the paragraph, so +it will not be stretched by full justification. +Third arg NOSQUEEZE non-nil means to leave interior whitespace unchanged, +otherwise it is made canonical." + (interactive) + (if (eq t how) (setq how (or (current-justification) 'none)) + (if (null how) (setq how 'full) + (or (memq how '(none left right center)) + (setq how 'full)))) + (or (memq how '(none left)) ; No action required for these. + (let ((fc (current-fill-column)) + (pos (point-marker)) + fp-end ; point at end of fill prefix + beg ; point at beginning of line's text + end ; point at end of line's text + indent ; column of `beg' + endcol ; column of `end' + ncols) ; new indent point or offset + (end-of-line) + ;; Check if this is the last line of the paragraph. + (if (and use-hard-newlines (null eop) + (get-text-property (point) 'hard)) + (setq eop t)) + (skip-chars-backward " \t") + ;; Quick exit if it appears to be properly justified already + ;; or there is no text. + (if (or (bolp) + (and (memq how '(full right)) + (= (current-column) fc))) + nil + (setq end (point)) + (beginning-of-line) + (skip-chars-forward " \t") + ;; Skip over fill-prefix. + (if (and fill-prefix + (not (string-equal fill-prefix "")) + (equal fill-prefix + (buffer-substring + (point) (min (point-max) (+ (length fill-prefix) + (point)))))) + (forward-char (length fill-prefix)) + (if (and adaptive-fill-mode + (looking-at adaptive-fill-regexp)) + (goto-char (match-end 0)))) + (setq fp-end (point)) + (skip-chars-forward " \t") + ;; This is beginning of the line's text. + (setq indent (current-column)) + (setq beg (point)) + (goto-char end) + (setq endcol (current-column)) + + ;; HOW can't be null or left--we would have exited already + (cond ((eq 'right how) + (setq ncols (- fc endcol)) + (if (< ncols 0) + ;; Need to remove some indentation + (delete-region + (progn (goto-char fp-end) + (if (< (current-column) (+ indent ncols)) + (move-to-column (+ indent ncols) t)) + (point)) + (progn (move-to-column indent) (point))) + ;; Need to add some + (goto-char beg) + (indent-to (+ indent ncols)) + ;; If point was at beginning of text, keep it there. + (if (= beg pos) + (move-marker pos (point))))) + + ((eq 'center how) + ;; Figure out how much indentation is needed + (setq ncols (+ (current-left-margin) + (/ (- fc (current-left-margin) ;avail. space + (- endcol indent)) ;text width + 2))) + (if (< ncols indent) + ;; Have too much indentation - remove some + (delete-region + (progn (goto-char fp-end) + (if (< (current-column) ncols) + (move-to-column ncols t)) + (point)) + (progn (move-to-column indent) (point))) + ;; Have too little - add some + (goto-char beg) + (indent-to ncols) + ;; If point was at beginning of text, keep it there. + (if (= beg pos) + (move-marker pos (point))))) + + ((eq 'full how) + ;; Insert extra spaces between words to justify line + (save-restriction + (narrow-to-region beg end) + (or nosqueeze + (canonically-space-region beg end)) + (goto-char (point-max)) + (setq ncols (- fc endcol)) + ;; Ncols is number of additional spaces needed + (if (> ncols 0) + (if (and (not eop) + ;; 97/3/14 jhod: Kinsoku + (find-space-insertable-point)) ;(search-backward " " nil t)) + (while (> ncols 0) + (let ((nmove (+ 3 (random 3)))) + (while (> nmove 0) + (or (find-space-insertable-point) ;(search-backward " " nil t) + (progn + (goto-char (point-max)) + (find-space-insertable-point))) ;(search-backward " "))) + (skip-chars-backward " ") + (setq nmove (1- nmove)))) + ;; XEmacs change + (insert " ") + (skip-chars-backward " ") + (setq ncols (1- ncols))))))) + (t (error "Unknown justification value")))) + (goto-char pos) + (move-marker pos nil))) + nil) + +(defun unjustify-current-line () + "Remove justification whitespace from current line. +If the line is centered or right-justified, this function removes any +indentation past the left margin. If the line is full-justified, it removes +extra spaces between words. It does nothing in other justification modes." + (let ((justify (current-justification))) + (cond ((eq 'left justify) nil) + ((eq nil justify) nil) + ((eq 'full justify) ; full justify: remove extra spaces + (beginning-of-line-text) + (canonically-space-region + (point) (save-excursion (end-of-line) (point)))) + ((memq justify '(center right)) + (save-excursion + (move-to-left-margin nil t) + ;; Position ourselves after any fill-prefix. + (if (and fill-prefix + (not (string-equal fill-prefix "")) + (equal fill-prefix + (buffer-substring + (point) (min (point-max) (+ (length fill-prefix) + (point)))))) + (forward-char (length fill-prefix))) + (delete-region (point) (progn (skip-chars-forward " \t") + (point)))))))) + +(defun unjustify-region (&optional begin end) + "Remove justification whitespace from region. +For centered or right-justified regions, this function removes any indentation +past the left margin from each line. For full-justified lines, it removes +extra spaces between words. It does nothing in other justification modes. +Arguments BEGIN and END are optional; default is the whole buffer." + (save-excursion + (save-restriction + (if end (narrow-to-region (point-min) end)) + (goto-char (or begin (point-min))) + (while (not (eobp)) + (unjustify-current-line) + (forward-line 1))))) + + +(defun fill-nonuniform-paragraphs (min max &optional justifyp mailp) + "Fill paragraphs within the region, allowing varying indentation within each. +This command divides the region into \"paragraphs\", +only at paragraph-separator lines, then fills each paragraph +using as the fill prefix the smallest indentation of any line +in the paragraph. + +When calling from a program, pass range to fill as first two arguments. + +Optional third and fourth arguments JUSTIFY and MAIL-FLAG: +JUSTIFY to justify paragraphs (prefix arg), +MAIL-FLAG for a mail message, i. e. don't fill header lines." + (interactive (list (region-beginning) (region-end) + (if current-prefix-arg 'full))) + (let ((fill-individual-varying-indent t)) + (fill-individual-paragraphs min max justifyp mailp))) + +(defun fill-individual-paragraphs (min max &optional justify mailp) + "Fill paragraphs of uniform indentation within the region. +This command divides the region into \"paragraphs\", +treating every change in indentation level as a paragraph boundary, +then fills each paragraph using its indentation level as the fill prefix. + +When calling from a program, pass range to fill as first two arguments. + +Optional third and fourth arguments JUSTIFY and MAIL-FLAG: +JUSTIFY to justify paragraphs (prefix arg), +MAIL-FLAG for a mail message, i. e. don't fill header lines." + (interactive (list (region-beginning) (region-end) + (if current-prefix-arg 'full))) + (save-restriction + (save-excursion + (goto-char min) + (beginning-of-line) + (narrow-to-region (point) max) + (if mailp + (while (and (not (eobp)) + (or (looking-at "[ \t]*[^ \t\n]+:") + (looking-at "[ \t]*$"))) + (if (looking-at "[ \t]*[^ \t\n]+:") + (search-forward "\n\n" nil 'move) + (forward-line 1)))) + (narrow-to-region (point) max) + ;; Loop over paragraphs. + (while (progn (skip-chars-forward " \t\n") (not (eobp))) + (move-to-left-margin) + (let ((start (point)) + fill-prefix fill-prefix-regexp) + ;; Find end of paragraph, and compute the smallest fill-prefix + ;; that fits all the lines in this paragraph. + (while (progn + ;; Update the fill-prefix on the first line + ;; and whenever the prefix good so far is too long. + (if (not (and fill-prefix + (looking-at fill-prefix-regexp))) + (setq fill-prefix + (if (and adaptive-fill-mode adaptive-fill-regexp + (looking-at adaptive-fill-regexp)) + (match-string 0) + (buffer-substring + (point) + (save-excursion (skip-chars-forward " \t") + (point)))) + fill-prefix-regexp (regexp-quote fill-prefix))) + (forward-line 1) + (if (bolp) + ;; If forward-line went past a newline + ;; move further to the left margin. + (move-to-left-margin)) + ;; Now stop the loop if end of paragraph. + (and (not (eobp)) + (if fill-individual-varying-indent + ;; If this line is a separator line, with or + ;; without prefix, end the paragraph. + (and + (not (looking-at paragraph-separate)) + (save-excursion + (not (and (looking-at fill-prefix-regexp) + ;; XEmacs change + (progn + (forward-char (length fill-prefix)) + (looking-at paragraph-separate)))))) + ;; If this line has more or less indent + ;; than the fill prefix wants, end the paragraph. + (and (looking-at fill-prefix-regexp) + (save-excursion + (not + (progn + (forward-char (length fill-prefix)) + (or (looking-at paragraph-separate) + (looking-at paragraph-start)))))))))) + ;; Fill this paragraph, but don't add a newline at the end. + (let ((had-newline (bolp))) + (fill-region-as-paragraph start (point) justify) + (or had-newline (delete-char -1)))))))) + +;;; fill.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/float-sup.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/float-sup.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,67 @@ +;;; float-sup.el --- detect absence of floating-point support in XEmacs runtime + +;; Copyright (C) 1985-7, 1997 Free Software Foundation, Inc. + +;; Maintainer: FSF +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. + +;;; Code: + +;; This file is dumped with XEmacs. + +;; Provide a meaningful error message if we are running on +;; bare (non-float) emacs. +;; Can't test for 'floatp since that may be defined by float-imitation +;; packages like float.el in this very directory. + +;; XEmacs change +(or (featurep 'lisp-float-type) + (error "Floating point was disabled at compile time")) + +;; define pi and e via math-lib calls. (much less prone to killer typos.) +;; XEmacs change (purecopy) +(defconst pi (purecopy (* 4 (atan 1))) "The value of Pi (3.1415926...)") +(defconst e (purecopy (exp 1)) "The value of e (2.7182818...)") + +;; Careful when editing this file ... typos here will be hard to spot. +;; (defconst pi 3.14159265358979323846264338327 +;; "The value of Pi (3.14159265358979323846264338327...)") + +;; XEmacs change (purecopy) +(defconst degrees-to-radians (purecopy (/ pi 180.0)) + "Degrees to radian conversion constant") +(defconst radians-to-degrees (purecopy (/ 180.0 pi)) + "Radian to degree conversion constant") + +;; these expand to a single multiply by a float when byte compiled + +(defmacro degrees-to-radians (x) + "Convert ARG from degrees to radians." + (list '* (/ pi 180.0) x)) +(defmacro radians-to-degrees (x) + "Convert ARG from radians to degrees." + (list '* (/ 180.0 pi) x)) + +;; Provided in C code in XEmacs +;; (provide 'lisp-float-type) + +;;; float-sup.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/format.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/format.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,833 @@ +;;; format.el --- read and save files in multiple formats + +;; Copyright (c) 1994, 1995, 1997 Free Software Foundation + +;; Author: Boris Goldowsky +;; Keywords: extensions, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Emacs/Mule zeta. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; This file defines a unified mechanism for saving & loading files stored +;; in different formats. `format-alist' contains information that directs +;; Emacs to call an encoding or decoding function when reading or writing +;; files that match certain conditions. +;; +;; When a file is visited, its format is determined by matching the +;; beginning of the file against regular expressions stored in +;; `format-alist'. If this fails, you can manually translate the buffer +;; using `format-decode-buffer'. In either case, the formats used are +;; listed in the variable `buffer-file-format', and become the default +;; format for saving the buffer. To save a buffer in a different format, +;; change this variable, or use `format-write-file'. +;; +;; Auto-save files are normally created in the same format as the visited +;; file, but the variable `auto-save-file-format' can be set to a +;; particularly fast or otherwise preferred format to be used for +;; auto-saving (or nil to do no encoding on auto-save files, but then you +;; risk losing any text-properties in the buffer). +;; +;; You can manually translate a buffer into or out of a particular format +;; with the functions `format-encode-buffer' and `format-decode-buffer'. +;; To translate just the region use the functions `format-encode-region' +;; and `format-decode-region'. +;; +;; You can define a new format by writing the encoding and decoding +;; functions, and adding an entry to `format-alist'. See enriched.el for +;; an example of how to implement a file format. There are various +;; functions defined in this file that may be useful for writing the +;; encoding and decoding functions: +;; * `format-annotate-region' and `format-deannotate-region' allow a +;; single alist of information to be used for encoding and decoding. +;; The alist defines a correspondence between strings in the file +;; ("annotations") and text-properties in the buffer. +;; * `format-replace-strings' is similarly useful for doing simple +;; string->string translations in a reversible manner. + +;;; Code: + +(put 'buffer-file-format 'permanent-local t) + +(defvar format-alist + '((image/jpeg "JPEG image" "\377\330\377\340\000\020JFIF" + image-decode-jpeg nil t image-mode) + (image/gif "GIF image" "GIF8[79]" + image-decode-gif nil t image-mode) + (image/png "Portable Network Graphics" "\211PNG" + image-decode-png nil t image-mode) + (image/x-xpm "XPM image" "/\\* XPM \\*/" + image-decode-xpm nil t image-mode) + (text/enriched "Extended MIME text/enriched format." + "Content-[Tt]ype:[ \t]*text/enriched" + enriched-decode enriched-encode t enriched-mode) + (text/richtext "Extended MIME obsolete text/richtext format." + "Content-[Tt]ype:[ \t]*text/richtext" + richtext-decode richtext-encode t enriched-mode) + (plain "Standard ASCII format, no text properties." + ;; Plain only exists so that there is an obvious neutral choice in + ;; the completion list. + nil nil nil nil nil)) + "List of information about understood file formats. +Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN). +NAME is a symbol, which is stored in `buffer-file-format'. +DOC-STR should be a single line providing more information about the + format. It is currently unused, but in the future will be shown to + the user if they ask for more information. +REGEXP is a regular expression to match against the beginning of the file; + it should match only files in that format. +FROM-FN is called to decode files in that format; it gets two args, BEGIN + and END, and can make any modifications it likes, returning the new + end. It must make sure that the beginning of the file no longer + matches REGEXP, or else it will get called again. +TO-FN is called to encode a region into that format; it is passed three + arguments: BEGIN, END, and BUFFER. BUFFER is the original buffer that + the data being written came from, which the function could use, for + example, to find the values of local variables. TO-FN should either + return a list of annotations like `write-region-annotate-functions', + or modify the region and return the new end. +MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil, + TO-FN will not make any changes but will instead return a list of + annotations. +MODE-FN, if specified, is called when visiting a file with that format.") + +;;; Basic Functions (called from Lisp) + +(defun format-annotate-function (format from to) + "Returns annotations for writing region as FORMAT. +FORMAT is a symbol naming one of the formats defined in `format-alist', +it must be a single symbol, not a list like `buffer-file-format'. +FROM and TO delimit the region to be operated on in the current buffer. +This function works like a function on `write-region-annotate-functions': +it either returns a list of annotations, or returns with a different buffer +current, which contains the modified text to write. + +For most purposes, consider using `format-encode-region' instead." + ;; This function is called by write-region (actually build-annotations) + ;; for each element of buffer-file-format. + (let* ((info (assq format format-alist)) + (to-fn (nth 4 info)) + (modify (nth 5 info))) + (if to-fn + (if modify + ;; To-function wants to modify region. Copy to safe place. + (let ((copy-buf (get-buffer-create " *Format Temp*"))) + (copy-to-buffer copy-buf from to) + (set-buffer copy-buf) + (format-insert-annotations write-region-annotations-so-far from) + (funcall to-fn (point-min) (point-max)) + nil) + ;; Otherwise just call function, it will return annotations. + (funcall to-fn from to))))) + +(defun format-decode (format length &optional visit-flag) + ;; This function is called by insert-file-contents whenever a file is read. + "Decode text from any known FORMAT. +FORMAT is a symbol appearing in `format-alist' or a list of such symbols, +or nil, in which case this function tries to guess the format of the data by +matching against the regular expressions in `format-alist'. After a match is +found and the region decoded, the alist is searched again from the beginning +for another match. + +Second arg LENGTH is the number of characters following point to operate on. +If optional third arg VISIT-FLAG is true, set `buffer-file-format' +to the list of formats used, and call any mode functions defined for those +formats. + +Returns the new length of the decoded region. + +For most purposes, consider using `format-decode-region' instead." + (let ((mod (buffer-modified-p)) + (begin (point)) + (end (+ (point) length))) + (if (null format) + ;; Figure out which format it is in, remember list in `format'. + (let ((try format-alist)) + (while try + (let* ((f (car try)) + (regexp (nth 2 f)) + (p (point))) + (if (and regexp (looking-at regexp) + (< (match-end 0) (+ begin length))) + (progn + (setq format (cons (car f) format)) + ;; Decode it + (if (nth 3 f) (setq end (funcall (nth 3 f) begin end))) + ;; Call visit function if required + (if (and visit-flag (nth 6 f)) (funcall (nth 6 f) 1)) + ;; Safeguard against either of the functions changing pt. + (goto-char p) + ;; Rewind list to look for another format + (setq try format-alist)) + (setq try (cdr try)))))) + ;; Deal with given format(s) + (or (listp format) (setq format (list format))) + (let ((do format) f) + (while do + (or (setq f (assq (car do) format-alist)) + (error "Unknown format" (car do))) + ;; Decode: + (if (nth 3 f) (setq end (funcall (nth 3 f) begin end))) + ;; Call visit function if required + (if (and visit-flag (nth 6 f)) (funcall (nth 6 f) 1)) + (setq do (cdr do))))) + (if visit-flag + (setq buffer-file-format format)) + (set-buffer-modified-p mod) + ;; Return new length of region + (- end begin))) + +;;; +;;; Interactive functions & entry points +;;; + +(defun format-decode-buffer (&optional format) + "Translate the buffer from some FORMAT. +If the format is not specified, this function attempts to guess. +`buffer-file-format' is set to the format used, and any mode-functions +for the format are called." + (interactive + (list (format-read "Translate buffer from format (default: guess): "))) + (save-excursion + (goto-char (point-min)) + (format-decode format (buffer-size) t))) + +(defun format-decode-region (from to &optional format) + "Decode the region from some format. +Arg FORMAT is optional; if omitted the format will be determined by looking +for identifying regular expressions at the beginning of the region." + (interactive + (list (region-beginning) (region-end) + (format-read "Translate region from format (default: guess): "))) + (save-excursion + (goto-char from) + (format-decode format (- to from) nil))) + +(defun format-encode-buffer (&optional format) + "Translate the buffer into FORMAT. +FORMAT defaults to `buffer-file-format'. It is a symbol naming one of the +formats defined in `format-alist', or a list of such symbols." + (interactive + (list (format-read (format "Translate buffer to format (default %s): " + buffer-file-format)))) + (format-encode-region (point-min) (point-max) format)) + +(defun format-encode-region (beg end &optional format) + "Translate the region into some FORMAT. +FORMAT defaults to `buffer-file-format', it is a symbol naming +one of the formats defined in `format-alist', or a list of such symbols." + (interactive + (list (region-beginning) (region-end) + (format-read (format "Translate region to format (default %s): " + buffer-file-format)))) + (if (null format) (setq format buffer-file-format)) + (if (symbolp format) (setq format (list format))) + (save-excursion + (goto-char end) + (let ( ; (cur-buf (current-buffer)) + (end (point-marker))) + (while format + (let* ((info (assq (car format) format-alist)) + (to-fn (nth 4 info)) + (modify (nth 5 info)) + ;; result + ) + (if to-fn + (if modify + (setq end (funcall to-fn beg end (current-buffer))) + (format-insert-annotations + (funcall to-fn beg end (current-buffer))))) + (setq format (cdr format))))))) + +(defun format-write-file (filename format) + "Write current buffer into a FILE using some FORMAT. +Makes buffer visit that file and sets the format as the default for future +saves. If the buffer is already visiting a file, you can specify a directory +name as FILE, to write a file of the same old name in that directory." + (interactive + ;; Same interactive spec as write-file, plus format question. + (let* ((file (if buffer-file-name + (read-file-name "Write file: " + nil nil nil nil) + (read-file-name "Write file: " + (cdr (assq 'default-directory + (buffer-local-variables))) + nil nil (buffer-name)))) + (fmt (format-read (format "Write file `%s' in format: " + (file-name-nondirectory file))))) + (list file fmt))) + (setq buffer-file-format format) + (write-file filename)) + +(defun format-find-file (filename format) + "Find the file FILE using data format FORMAT. +If FORMAT is nil then do not do any format conversion." + (interactive + ;; Same interactive spec as write-file, plus format question. + (let* ((file (read-file-name "Find file: ")) + (fmt (format-read (format "Read file `%s' in format: " + (file-name-nondirectory file))))) + (list file fmt))) + (let ((format-alist nil)) + (find-file filename)) + (if format + (format-decode-buffer format))) + +(defun format-insert-file (filename format &optional beg end) + "Insert the contents of file FILE using data format FORMAT. +If FORMAT is nil then do not do any format conversion. +The optional third and fourth arguments BEG and END specify +the part of the file to read. + +The return value is like the value of `insert-file-contents': +a list (ABSOLUTE-FILE-NAME . SIZE)." + (interactive + ;; Same interactive spec as write-file, plus format question. + (let* ((file (read-file-name "Find file: ")) + (fmt (format-read (format "Read file `%s' in format: " + (file-name-nondirectory file))))) + (list file fmt))) + (let (value size) + (let ((format-alist nil)) + (setq value (insert-file-contents filename nil beg end)) + (setq size (nth 1 value))) + (if format + (setq size (format-decode format size) + value (cons (car value) size))) + value)) + +(defun format-read (&optional prompt) + "Read and return the name of a format. +Return value is a list, like `buffer-file-format'; it may be nil. +Formats are defined in `format-alist'. Optional arg is the PROMPT to use." + (let* ((table (mapcar (lambda (x) (list (symbol-name (car x)))) + format-alist)) + (ans (completing-read (or prompt "Format: ") table nil t))) + (if (not (equal "" ans)) (list (intern ans))))) + + +;;; +;;; Below are some functions that may be useful in writing encoding and +;;; decoding functions for use in format-alist. +;;; + +(defun format-replace-strings (alist &optional reverse beg end) + "Do multiple replacements on the buffer. +ALIST is a list of (from . to) pairs, which should be proper arguments to +`search-forward' and `replace-match' respectively. +Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that +you can use the same list in both directions if it contains only literal +strings. +Optional args BEGIN and END specify a region of the buffer to operate on." + (save-excursion + (save-restriction + (or beg (setq beg (point-min))) + (if end (narrow-to-region (point-min) end)) + (while alist + (let ((from (if reverse (cdr (car alist)) (car (car alist)))) + (to (if reverse (car (cdr alist)) (cdr (car alist))))) + (goto-char beg) + (while (search-forward from nil t) + (goto-char (match-beginning 0)) + (insert to) + (set-text-properties (- (point) (length to)) (point) + (text-properties-at (point))) + (delete-region (point) (+ (point) (- (match-end 0) + (match-beginning 0))))) + (setq alist (cdr alist))))))) + +;;; Some list-manipulation functions that we need. + +(defun format-delq-cons (cons list) + "Remove the given CONS from LIST by side effect, +and return the new LIST. Since CONS could be the first element +of LIST, write `\(setq foo \(format-delq-cons element foo))' to be sure of +changing the value of `foo'." + (if (eq cons list) + (cdr list) + (let ((p list)) + (while (not (eq (cdr p) cons)) + (if (null p) (error "format-delq-cons: not an element.")) + (setq p (cdr p))) + ;; Now (cdr p) is the cons to delete + (setcdr p (cdr cons)) + list))) + +(defun format-make-relatively-unique (a b) + "Delete common elements of lists A and B, return as pair. +Compares using `equal'." + (let* ((acopy (copy-sequence a)) + (bcopy (copy-sequence b)) + (tail acopy)) + (while tail + (let ((dup (member (car tail) bcopy)) + (next (cdr tail))) + (if dup (setq acopy (format-delq-cons tail acopy) + bcopy (format-delq-cons dup bcopy))) + (setq tail next))) + (cons acopy bcopy))) + +(defun format-common-tail (a b) + "Given two lists that have a common tail, return it. +Compares with `equal', and returns the part of A that is equal to the +equivalent part of B. If even the last items of the two are not equal, +returns nil." + (let ((la (length a)) + (lb (length b))) + ;; Make sure they are the same length + (if (> la lb) + (setq a (nthcdr (- la lb) a)) + (setq b (nthcdr (- lb la) b)))) + (while (not (equal a b)) + (setq a (cdr a) + b (cdr b))) + a) + +(defun format-reorder (items order) + "Arrange ITEMS to following partial ORDER. +Elements of ITEMS equal to elements of ORDER will be rearranged to follow the +ORDER. Unmatched items will go last." + (if order + (let ((item (member (car order) items))) + (if item + (cons (car item) + (format-reorder (format-delq-cons item items) + (cdr order))) + (format-reorder items (cdr order)))) + items)) + +(put 'face 'format-list-valued t) ; These text-properties take values +(put 'unknown 'format-list-valued t) ; that are lists, the elements of which + ; should be considered separately. + ; See format-deannotate-region and + ; format-annotate-region. + +;;; +;;; Decoding +;;; + +(defun format-deannotate-region (from to translations next-fn) + "Translate annotations in the region into text properties. +This sets text properties between FROM to TO as directed by the +TRANSLATIONS and NEXT-FN arguments. + +NEXT-FN is a function that searches forward from point for an annotation. +It should return a list of 4 elements: \(BEGIN END NAME POSITIVE). BEGIN and +END are buffer positions bounding the annotation, NAME is the name searched +for in TRANSLATIONS, and POSITIVE should be non-nil if this annotation marks +the beginning of a region with some property, or nil if it ends the region. +NEXT-FN should return nil if there are no annotations after point. + +The basic format of the TRANSLATIONS argument is described in the +documentation for the `format-annotate-region' function. There are some +additional things to keep in mind for decoding, though: + +When an annotation is found, the TRANSLATIONS list is searched for a +text-property name and value that corresponds to that annotation. If the +text-property has several annotations associated with it, it will be used only +if the other annotations are also in effect at that point. The first match +found whose annotations are all present is used. + +The text property thus determined is set to the value over the region between +the opening and closing annotations. However, if the text-property name has a +non-nil `format-list-valued' property, then the value will be consed onto the +surrounding value of the property, rather than replacing that value. + +There are some special symbols that can be used in the \"property\" slot of +the TRANSLATIONS list: PARAMETER and FUNCTION \(spelled in uppercase). +Annotations listed under the pseudo-property PARAMETER are considered to be +arguments of the immediately surrounding annotation; the text between the +opening and closing parameter annotations is deleted from the buffer but saved +as a string. The surrounding annotation should be listed under the +pseudo-property FUNCTION. Instead of inserting a text-property for this +annotation, the function listed in the VALUE slot is called to make whatever +changes are appropriate. The function's first two arguments are the START and +END locations, and the rest of the arguments are any PARAMETERs found in that +region. + +Any annotations that are found by NEXT-FN but not defined by TRANSLATIONS +are saved as values of the `unknown' text-property \(which is list-valued). +The TRANSLATIONS list should usually contain an entry of the form + \(unknown \(nil format-annotate-value)) +to write these unknown annotations back into the file." + (save-excursion + (save-restriction + (narrow-to-region (point-min) to) + (goto-char from) + (let (next open-ans todo + ;; loc + unknown-ans) + (while (setq next (funcall next-fn)) + (let* ((loc (nth 0 next)) + (end (nth 1 next)) + (name (nth 2 next)) + (positive (nth 3 next)) + (found nil)) + + ;; Delete the annotation + (delete-region loc end) + (if positive + ;; Positive annotations are stacked, remembering location + (setq open-ans (cons (list name loc) open-ans)) + ;; It is a negative annotation: + ;; Close the top annotation & add its text property. + ;; If the file's nesting is messed up, the close might not match + ;; the top thing on the open-annotations stack. + ;; If no matching annotation is open, just ignore the close. + (if (not (assoc name open-ans)) + (message "Extra closing annotation (%s) in file" name) + ;; If one is open, but not on the top of the stack, close + ;; the things in between as well. Set `found' when the real + ;; one is closed. + (while (not found) + (let* ((top (car open-ans)) ; first on stack: should match. + (top-name (car top)) + (start (car (cdr top))) ; location of start + (params (cdr (cdr top))) ; parameters + (aalist translations) + (matched nil)) + (if (equal name top-name) + (setq found t) + (message "Improper nesting in file.")) + ;; Look through property names in TRANSLATIONS + (while aalist + (let ((prop (car (car aalist))) + (alist (cdr (car aalist)))) + ;; And look through values for each property + (while alist + (let ((value (car (car alist))) + (ans (cdr (car alist)))) + (if (member top-name ans) + ;; This annotation is listed, but still have to + ;; check if multiple annotations are satisfied + (if (member 'nil (mapcar + (lambda (r) + (assoc r open-ans)) + ans)) + nil ; multiple ans not satisfied + ;; Yes, all set. + ;; If there are multiple annotations going + ;; into one text property, adjust the + ;; begin points of the other annotations + ;; so that we don't get double marking. + (let ((to-reset ans) + this-one) + (while to-reset + (setq this-one + (assoc (car to-reset) + (cdr open-ans))) + (if this-one + (setcar (cdr this-one) loc)) + (setq to-reset (cdr to-reset)))) + ;; Set loop variables to nil so loop + ;; will exit. + (setq alist nil aalist nil matched t + ;; pop annotation off stack. + open-ans (cdr open-ans)) + (cond + ;; Check for pseudo-properties + ((eq prop 'PARAMETER) + ;; This is a parameter of the top open ann: + ;; delete text and use as arg. + (if open-ans + ;; (If nothing open, discard). + (setq open-ans + (cons (append (car open-ans) + (list + (buffer-substring + start loc))) + (cdr open-ans)))) + (delete-region start loc)) + ((eq prop 'FUNCTION) + ;; Not a property, but a function to call. + (let ((rtn (apply value start loc params))) + (if rtn (setq todo (cons rtn todo))))) + (t + ;; Normal property/value pair + (setq todo + (cons (list start loc prop value) + todo))))))) + (setq alist (cdr alist)))) + (setq aalist (cdr aalist))) + (if matched + nil + ;; Didn't find any match for the annotation: + ;; Store as value of text-property `unknown'. + (setq open-ans (cdr open-ans)) + (setq todo (cons (list start loc 'unknown top-name) + todo)) + (setq unknown-ans (cons name unknown-ans))))))))) + + ;; Once entire file has been scanned, add the properties. + (while todo + (let* ((item (car todo)) + (from (nth 0 item)) + (to (nth 1 item)) + (prop (nth 2 item)) + (val (nth 3 item))) + + (put-text-property + from to prop + (cond ((numberp val) ; add to ambient value if numeric + (+ val (or (get-text-property from prop) 0))) + ((get prop 'format-list-valued) ; value gets consed onto + ; list-valued properties + (let ((prev (get-text-property from prop))) + (cons val (if (listp prev) prev (list prev))))) + (t val)))) ; normally, just set to val. + (setq todo (cdr todo))) + + (if unknown-ans + (message "Unknown annotations: %s" unknown-ans)))))) + +;;; +;;; Encoding +;;; + +(defun format-insert-annotations (list &optional offset) + "Apply list of annotations to buffer as `write-region' would. +Inserts each element of the given LIST of buffer annotations at its +appropriate place. Use second arg OFFSET if the annotations' locations are +not relative to the beginning of the buffer: annotations will be inserted +at their location-OFFSET+1 \(ie, the offset is treated as the character number +of the first character in the buffer)." + (if (not offset) + (setq offset 0) + (setq offset (1- offset))) + (let ((l (reverse list))) + (while l + (goto-char (- (car (car l)) offset)) + (insert (cdr (car l))) + (setq l (cdr l))))) + +(defun format-annotate-value (old new) + "Return OLD and NEW as a \(close . open) annotation pair. +Useful as a default function for TRANSLATIONS alist when the value of the text +property is the name of the annotation that you want to use, as it is for the +`unknown' text property." + (cons (if old (list old)) + (if new (list new)))) + +(defun format-annotate-region (from to trans format-fn ignore) + "Generate annotations for text properties in the region. +Searches for changes between FROM and TO, and describes them with a list of +annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text +properties not to consider; any text properties that are neither ignored nor +listed in TRANSLATIONS are warned about. +If you actually want to modify the region, give the return value of this +function to `format-insert-annotations'. + +Format of the TRANSLATIONS argument: + +Each element is a list whose car is a PROPERTY, and the following +elements are VALUES of that property followed by the names of zero or more +ANNOTATIONS. Whenever the property takes on that value, the annotations +\(as formatted by FORMAT-FN) are inserted into the file. +When the property stops having that value, the matching negated annotation +will be inserted \(it may actually be closed earlier and reopened, if +necessary, to keep proper nesting). + +If the property's value is a list, then each element of the list is dealt with +separately. + +If a VALUE is numeric, then it is assumed that there is a single annotation +and each occurrence of it increments the value of the property by that number. +Thus, given the entry \(left-margin \(4 \"indent\")), if the left margin +changes from 4 to 12, two annotations will be generated. + +If the VALUE is nil, then instead of annotations, a function should be +specified. This function is used as a default: it is called for all +transitions not explicitly listed in the table. The function is called with +two arguments, the OLD and NEW values of the property. It should return +lists of annotations like `format-annotate-location' does. + + The same structure can be used in reverse for reading files." + (let ((all-ans nil) ; All annotations - becomes return value + (open-ans nil) ; Annotations not yet closed + (loc nil) ; Current location + (not-found nil)) ; Properties that couldn't be saved + (while (or (null loc) + (and (setq loc (next-property-change loc nil to)) + (< loc to))) + (or loc (setq loc from)) + (let* ((ans (format-annotate-location loc (= loc from) ignore trans)) + (neg-ans (format-reorder (aref ans 0) open-ans)) + (pos-ans (aref ans 1)) + (ignored (aref ans 2))) + (setq not-found (append ignored not-found) + ignore (append ignored ignore)) + ;; First do the negative (closing) annotations + (while neg-ans + ;; Check if it's missing. This can happen (eg, a numeric property + ;; going negative can generate closing annotations before there are + ;; any open). Warn user & ignore. + (if (not (member (car neg-ans) open-ans)) + (message "Can't close %s: not open." (car neg-ans)) + (while (not (equal (car neg-ans) (car open-ans))) + ;; To close anno. N, need to first close ans 1 to N-1, + ;; remembering to re-open them later. + (setq pos-ans (cons (car open-ans) pos-ans)) + (setq all-ans + (cons (cons loc (funcall format-fn (car open-ans) nil)) + all-ans)) + (setq open-ans (cdr open-ans))) + ;; Now remove the one we're really interested in from open list. + (setq open-ans (cdr open-ans)) + ;; And put the closing annotation here. + (setq all-ans + (cons (cons loc (funcall format-fn (car neg-ans) nil)) + all-ans))) + (setq neg-ans (cdr neg-ans))) + ;; Now deal with positive (opening) annotations + (let ( ; (p pos-ans) + ) + (while pos-ans + (setq open-ans (cons (car pos-ans) open-ans)) + (setq all-ans + (cons (cons loc (funcall format-fn (car pos-ans) t)) + all-ans)) + (setq pos-ans (cdr pos-ans)))))) + + ;; Close any annotations still open + (while open-ans + (setq all-ans + (cons (cons to (funcall format-fn (car open-ans) nil)) + all-ans)) + (setq open-ans (cdr open-ans))) + (if not-found + (message "These text properties could not be saved:\n %s" + not-found)) + (nreverse all-ans))) + +;;; Internal functions for format-annotate-region. + +(defun format-annotate-location (loc all ignore trans) + "Return annotation(s) needed at LOCATION. +This includes any properties that change between LOC-1 and LOC. +If ALL is true, don't look at previous location, but generate annotations for +all non-nil properties. +Third argument IGNORE is a list of text-properties not to consider. + +Return value is a vector of 3 elements: +1. List of names of the annotations to close +2. List of the names of annotations to open. +3. List of properties that were ignored or couldn't be annotated." + (let* ((prev-loc (1- loc)) + (before-plist (if all nil (text-properties-at prev-loc))) + (after-plist (text-properties-at loc)) + p negatives positives prop props not-found) + ;; make list of all property names involved + (setq p before-plist) + (while p + (if (not (memq (car p) props)) + (setq props (cons (car p) props))) + (setq p (cdr (cdr p)))) + (setq p after-plist) + (while p + (if (not (memq (car p) props)) + (setq props (cons (car p) props))) + (setq p (cdr (cdr p)))) + + (while props + (setq prop (car props) + props (cdr props)) + (if (memq prop ignore) + nil ; If it's been ignored before, ignore it now. + (let ((before (if all nil (car (cdr (memq prop before-plist))))) + (after (car (cdr (memq prop after-plist))))) + (if (equal before after) + nil ; no change; ignore + (let ((result (format-annotate-single-property-change + prop before after trans))) + (if (not result) + (setq not-found (cons prop not-found)) + (setq negatives (nconc negatives (car result)) + positives (nconc positives (cdr result))))))))) + (vector negatives positives not-found))) + +(defun format-annotate-single-property-change (prop old new trans) + "Return annotations for PROPERTY changing from OLD to NEW. +These are searched for in the TRANSLATIONS alist. +If NEW does not appear in the list, but there is a default function, then that +function is called. +Annotations to open and to close are returned as a dotted pair." + (let ((prop-alist (cdr (assoc prop trans))) + ;; default + ) + (if (not prop-alist) + nil + ;; If property is numeric, nil means 0 + (cond ((and (numberp old) (null new)) + (setq new 0)) + ((and (numberp new) (null old)) + (setq old 0))) + ;; If either old or new is a list, have to treat both that way. + (if (or (consp old) (consp new)) + (let* ((old (if (listp old) old (list old))) + (new (if (listp new) new (list new))) + ;; (tail (format-common-tail old new)) + close open) + (while old + (setq close + (append (car (format-annotate-atomic-property-change + prop-alist (car old) nil)) + close) + old (cdr old))) + (while new + (setq open + (append (cdr (format-annotate-atomic-property-change + prop-alist nil (car new))) + open) + new (cdr new))) + (format-make-relatively-unique close open)) + (format-annotate-atomic-property-change prop-alist old new))))) + +(defun format-annotate-atomic-property-change (prop-alist old new) + "Internal function annotate a single property change. +PROP-ALIST is the relevant segment of a TRANSLATIONS list. +OLD and NEW are the values." + (cond + ;; Numerical annotation - use difference + ((and (numberp old) (numberp new)) + (let* ((entry (progn + (while (and (car (car prop-alist)) + (not (numberp (car (car prop-alist))))) + (setq prop-alist (cdr prop-alist))) + (car prop-alist))) + (increment (car (car prop-alist))) + (n (ceiling (/ (float (- new old)) (float increment)))) + (anno (car (cdr (car prop-alist))))) + (if (> n 0) + (cons nil (make-list n anno)) + (cons (make-list (- n) anno) nil)))) + + ;; Standard annotation + (t (let ((close (and old (cdr (assoc old prop-alist)))) + (open (and new (cdr (assoc new prop-alist))))) + (if (or close open) + (format-make-relatively-unique close open) + ;; Call "Default" function, if any + (let ((default (assq nil prop-alist))) + (if default + (funcall (car (cdr default)) old new)))))))) + +;;; format.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/frame.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/frame.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,1300 @@ +;;; frame.el --- multi-frame management independent of window systems. + +;; Copyright (C) 1993-4, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995, 1996 Ben Wing. + +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +(defgroup frames nil + "Support for Emacs frames and window systems." + :group 'environment) + +; No need for `frame-creation-function'. + +;;; The initial value given here for this must ask for a minibuffer. +;;; There must always exist a frame with a minibuffer, and after we +;;; delete the terminal frame, this will be the only frame. +(defcustom initial-frame-plist '(minibuffer t) + "Plist of frame properties for creating the initial X window frame. +You can set this in your `.emacs' file; for example, + (setq initial-frame-plist '(top 1 left 1 width 80 height 55)) +Properties specified here supersede the values given in `default-frame-plist'. +The format of this can also be an alist for backward compatibility. + +If the value calls for a frame without a minibuffer, and you have not created +a minibuffer frame on your own, one is created according to +`minibuffer-frame-plist'. + +You can specify geometry-related options for just the initial frame +by setting this variable in your `.emacs' file; however, they won't +take effect until Emacs reads `.emacs', which happens after first creating +the frame. If you want the frame to have the proper geometry as soon +as it appears, you need to use this three-step process: +* Specify X resources to give the geometry you want. +* Set `default-frame-plist' to override these options so that they + don't affect subsequent frames. +* Set `initial-frame-plist' in a way that matches the X resources, + to override what you put in `default-frame-plist'." + :type '(repeat (group :inline t + (symbol :tag "Property") + (sexp :tag "Value"))) + :group 'frames) + +(defcustom minibuffer-frame-plist '(width 80 height 2 menubar-visible-p nil + default-toolbar-visible-p nil) + "Plist of frame properties for initially creating a minibuffer frame. +You can set this in your `.emacs' file; for example, + (setq minibuffer-frame-plist '(top 1 left 1 width 80 height 2)) +Properties specified here supersede the values given in +`default-frame-plist'. +The format of this can also be an alist for backward compatibility." + :type '(repeat (group :inline t + (symbol :tag "Property") + (sexp :tag "Value"))) + :group 'frames) + +(defcustom pop-up-frame-plist nil + "Plist of frame properties used when creating pop-up frames. +Pop-up frames are used for completions, help, and the like. +This variable can be set in your init file, like this: + (setq pop-up-frame-plist '(width 80 height 20)) +These supersede the values given in `default-frame-plist'. +The format of this can also be an alist for backward compatibility." + :type '(repeat (group :inline t + (symbol :tag "Property") + (sexp :tag "Value"))) + :group 'frames) + +(setq pop-up-frame-function + (function (lambda () + (make-frame pop-up-frame-plist)))) + +(defcustom special-display-frame-plist '(height 14 width 80 unsplittable t) + "*Plist of frame properties used when creating special frames. +Special frames are used for buffers whose names are in +`special-display-buffer-names' and for buffers whose names match +one of the regular expressions in `special-display-regexps'. +This variable can be set in your init file, like this: + (setq special-display-frame-plist '(width 80 height 20)) +These supersede the values given in `default-frame-plist'. +The format of this can also be an alist for backward compatibility." + :type '(repeat (group :inline t + (symbol :tag "Property") + (sexp :tag "Value"))) + :group 'frames) + +(defun safe-alist-to-plist (cruftiness) + (if (consp (car cruftiness)) + (alist-to-plist cruftiness) + cruftiness)) + +;; Display BUFFER in its own frame, reusing an existing window if any. +;; Return the window chosen. +;; Currently we do not insist on selecting the window within its frame. +;; If ARGS is a plist, use it as a list of frame property specs. +;; #### Change, not compatible with FSF: This stuff is all so incredibly +;; junky anyway that I doubt it makes any difference. +;; If ARGS is a list whose car is t, +;; use (cadr ARGS) as a function to do the work. +;; Pass it BUFFER as first arg, and (cddr ARGS) gives the rest of the args. +(defun special-display-popup-frame (buffer &optional args) + ;; if we can't display simultaneous multiple frames, just return + ;; nil and let the normal behavior take over. + (and (device-on-window-system-p) + (if (and args (eq t (car args))) + (apply (cadr args) buffer (cddr args)) + (let ((window (get-buffer-window buffer t))) + (if window + ;; If we have a window already, make it visible. + (let ((frame (window-frame window))) + (make-frame-visible frame) + (raise-frame frame) + window) + ;; If no window yet, make one in a new frame. + (let ((frame + (make-frame (append (safe-alist-to-plist args) + (safe-alist-to-plist + special-display-frame-plist))))) + (set-window-buffer (frame-selected-window frame) buffer) + (set-window-dedicated-p (frame-selected-window frame) t) + (frame-selected-window frame))))))) + +(setq special-display-function 'special-display-popup-frame) + +;;; Handle delete-frame events from the X server. +;(defun handle-delete-frame (event) +; (interactive "e") +; (let ((frame (posn-window (event-start event))) +; (i 0) +; (tail (frame-list))) +; (while tail +; (and (frame-visible-p (car tail)) +; (not (eq (car tail) frame)) +; (setq i (1+ i))) +; (setq tail (cdr tail))) +; (if (> i 0) +; (delete-frame frame t) +; (kill-emacs)))) + + +;;;; Arrangement of frames at startup + +;;; 1) Load the window system startup file from the lisp library and read the +;;; high-priority arguments (-q and the like). The window system startup +;;; file should create any frames specified in the window system defaults. +;;; +;;; 2) If no frames have been opened, we open an initial text frame. +;;; +;;; 3) Once the init file is done, we apply any newly set properties +;;; in initial-frame-plist to the frame. + +;; These are now called explicitly at the proper times, +;; since that is easier to understand. +;; Actually using hooks within Emacs is bad for future maintenance. --rms. +;; (add-hook 'before-init-hook 'frame-initialize) +;; (add-hook 'window-setup-hook 'frame-notice-user-settings) + +;;; If we create the initial frame, this is it. +(defvar frame-initial-frame nil) + +;; Record the properties used in frame-initialize to make the initial frame. +(defvar frame-initial-frame-plist) + +(defvar frame-initial-geometry-arguments nil) + +(defun canonicalize-frame-plists () + (setq initial-frame-plist (safe-alist-to-plist initial-frame-plist)) + (setq default-frame-plist (safe-alist-to-plist default-frame-plist))) + +;;; startup.el calls this function before loading the user's init +;;; file - if there is no frame with a minibuffer open now, create +;;; one to display messages while loading the init file. +(defun frame-initialize () + ;; In batch mode, we actually use the initial terminal device for output. + (canonicalize-frame-plists) + (if (not (noninteractive)) + (progn + ;; Don't call select-frame here - focus is a matter of WM policy. + + ;; If there is no frame with a minibuffer besides the terminal + ;; frame, then we need to create the opening frame. Make sure + ;; it has a minibuffer, but let initial-frame-plist omit the + ;; minibuffer spec. + (or (delq terminal-frame (minibuffer-frame-list)) + (progn + (setq frame-initial-frame-plist + (append initial-frame-plist default-frame-plist)) + ;; FSFmacs has scroll-bar junk here that we don't need. + (setq default-minibuffer-frame + (setq frame-initial-frame + (make-frame initial-frame-plist + (car (delq terminal-device + (device-list)))))) + ;; Delete any specifications for window geometry properties + ;; so that we won't reapply them in frame-notice-user-settings. + ;; It would be wrong to reapply them then, + ;; because that would override explicit user resizing. + (setq initial-frame-plist + (frame-remove-geometry-props initial-frame-plist)))) + ;; At this point, we know that we have a frame open, so we + ;; can delete the terminal device. + (delete-device terminal-device) + (setq terminal-frame nil) + + ;; FSFmacs sets frame-creation-function here, but no need. + ))) + +;;; startup.el calls this function after loading the user's init +;;; file. Now default-frame-plist and initial-frame-plist contain +;;; information to which we must react; do what needs to be done. +(defun frame-notice-user-settings () + + ;; FSFmacs has menu-bar junk here that we don't need. + + (canonicalize-frame-plists) + + ;; Creating and deleting frames may shift the selected frame around, + ;; and thus the current buffer. Protect against that. We don't + ;; want to use save-excursion here, because that may also try to set + ;; the buffer of the selected window, which fails when the selected + ;; window is the minibuffer. + (let ((old-buffer (current-buffer))) + + ;; If the initial frame is still around, apply initial-frame-plist + ;; and default-frame-plist to it. + (if (frame-live-p frame-initial-frame) + + ;; The initial frame we create above always has a minibuffer. + ;; If the user wants to remove it, or make it a minibuffer-only + ;; frame, then we'll have to delete the current frame and make a + ;; new one; you can't remove or add a root window to/from an + ;; existing frame. + ;; + ;; NOTE: default-frame-plist was nil when we created the + ;; existing frame. We need to explicitly include + ;; default-frame-plist in the properties of the screen we + ;; create here, so that its new value, gleaned from the user's + ;; .emacs file, will be applied to the existing screen. + (if (not (eq (car + (or (and (lax-plist-member + initial-frame-plist 'minibuffer) + (list (lax-plist-get initial-frame-plist + 'minibuffer))) + (and (lax-plist-member default-frame-plist + 'minibuffer) + (list (lax-plist-get default-frame-plist + 'minibuffer))) + '(t))) + t)) + ;; Create the new frame. + (let (props + ) + ;; If the frame isn't visible yet, wait till it is. + ;; If the user has to position the window, + ;; Emacs doesn't know its real position until + ;; the frame is seen to be visible. + + (if (frame-property frame-initial-frame 'initially-unmapped) + nil + (while (not (frame-visible-p frame-initial-frame)) + (sleep-for 1))) + (setq props (frame-properties frame-initial-frame)) + ;; Get rid of `name' unless it was specified explicitly before. + (or (lax-plist-member frame-initial-frame-plist 'name) + (setq props (lax-plist-remprop props 'name))) + (setq props (append initial-frame-plist default-frame-plist + props + nil)) + ;; Get rid of `reverse', because that was handled + ;; when we first made the frame. + (laxputf props 'reverse nil) + ;; Get rid of `window-id', otherwise make-frame will + ;; think we're trying to setup an external widget. + (laxremf props 'window-id) + (if (lax-plist-member frame-initial-geometry-arguments 'height) + (laxremf props 'height)) + (if (lax-plist-member frame-initial-geometry-arguments 'width) + (laxremf props 'width)) + (if (lax-plist-member frame-initial-geometry-arguments 'left) + (laxremf props 'left)) + (if (lax-plist-member frame-initial-geometry-arguments 'top) + (laxremf props 'top)) + + ;; Now create the replacement initial frame. + (make-frame + ;; Use the geometry args that created the existing + ;; frame, rather than the props we get for it. + (append '(user-size t user-position t) + frame-initial-geometry-arguments + props)) + ;; The initial frame, which we are about to delete, may be + ;; the only frame with a minibuffer. If it is, create a + ;; new one. + (or (delq frame-initial-frame (minibuffer-frame-list)) + (make-initial-minibuffer-frame nil)) + + ;; If the initial frame is serving as a surrogate + ;; minibuffer frame for any frames, we need to wean them + ;; onto a new frame. The default-minibuffer-frame + ;; variable must be handled similarly. + (let ((users-of-initial + (filtered-frame-list + #'(lambda (frame) + (and (not (eq frame frame-initial-frame)) + (eq (window-frame + (minibuffer-window frame)) + frame-initial-frame)))))) + (if (or users-of-initial + (eq default-minibuffer-frame frame-initial-frame)) + + ;; Choose an appropriate frame. Prefer frames which + ;; are only minibuffers. + (let* ((new-surrogate + (car + (or (filtered-frame-list + #'(lambda (frame) + (eq 'only + (frame-property frame 'minibuffer)))) + (minibuffer-frame-list)))) + (new-minibuffer (minibuffer-window new-surrogate))) + + (if (eq default-minibuffer-frame frame-initial-frame) + (setq default-minibuffer-frame new-surrogate)) + + ;; Wean the frames using frame-initial-frame as + ;; their minibuffer frame. + (mapcar + #' + (lambda (frame) + (set-frame-property frame 'minibuffer + new-minibuffer)) + users-of-initial)))) + + ;; Redirect events enqueued at this frame to the new frame. + ;; Is this a good idea? + ;; Probably not, since this whole redirect-frame-focus + ;; stuff is a load of trash, and so is this function we're in. + ;; --ben + ;(redirect-frame-focus frame-initial-frame new) + + ;; Finally, get rid of the old frame. + (delete-frame frame-initial-frame t)) + + ;; Otherwise, we don't need all that rigamarole; just apply + ;; the new properties. + (let (newprops allprops tail) + (setq allprops (append initial-frame-plist + default-frame-plist)) + (if (lax-plist-member frame-initial-geometry-arguments 'height) + (laxremf allprops 'height)) + (if (lax-plist-member frame-initial-geometry-arguments 'width) + (remf allprops 'width)) + (if (lax-plist-member frame-initial-geometry-arguments 'left) + (laxremf allprops 'left)) + (if (lax-plist-member frame-initial-geometry-arguments 'top) + (laxremf allprops 'top)) + (setq tail allprops) + ;; Find just the props that have changed since we first + ;; made this frame. Those are the ones actually set by + ;; the init file. For those props whose values we already knew + ;; (such as those spec'd by command line options) + ;; it is undesirable to specify the parm again + ;; once the user has seen the frame and been able to alter it + ;; manually. + (while tail + (let (newval oldval) + (setq oldval (lax-plist-get frame-initial-frame-plist + (car tail))) + (setq newval (lax-plist-get allprops (car tail))) + (or (eq oldval newval) + (laxputf newprops (car tail) newval))) + (setq tail (cddr tail))) + (set-frame-properties frame-initial-frame newprops) + ;silly FSFmacs junk + ;if (lax-plist-member newprops 'font) + ; (frame-update-faces frame-initial-frame)) + + ))) + + ;; Restore the original buffer. + (set-buffer old-buffer) + + ;; Make sure the initial frame can be GC'd if it is ever deleted. + ;; Make sure frame-notice-user-settings does nothing if called twice. + (setq frame-initial-frame nil))) + +(defun make-initial-minibuffer-frame (device) + (let ((props (append '(minibuffer only) + (safe-alist-to-plist minibuffer-frame-plist)))) + (make-frame props device))) + + +;;;; Creation of additional frames, and other frame miscellanea + +(defun get-other-frame () + "Return some frame other than the current frame, creating one if necessary." + (let* ((this (selected-frame)) + ;; search visible frames first + (next (next-frame this 'visible-nomini))) + ;; then search iconified frames + (if (eq this next) + (setq next (next-frame 'visible-iconic-nomini))) + (if (eq this next) + ;; otherwise, make a new frame + (make-frame) + next))) + +(defun next-multiframe-window () + "Select the next window, regardless of which frame it is on." + (interactive) + (select-window (next-window (selected-window) + (> (minibuffer-depth) 0) + t))) + +(defun previous-multiframe-window () + "Select the previous window, regardless of which frame it is on." + (interactive) + (select-window (previous-window (selected-window) + (> (minibuffer-depth) 0) + t))) + +(defun make-frame-on-device (type connection &optional props) + "Create a frame of type TYPE on CONNECTION. +TYPE should be a symbol naming the device type, i.e. one of + +x An X display. CONNECTION should be a standard display string + such as \"unix:0\", or nil for the display specified on the + command line or in the DISPLAY environment variable. Only if + support for X was compiled into XEmacs. +tty A standard TTY connection or terminal. CONNECTION should be + a TTY device name such as \"/dev/ttyp2\" (as determined by + the Unix command `tty') or nil for XEmacs' standard input + and output (usually the TTY in which XEmacs started). Only + if support for TTY's was compiled into XEmacs. +ns A connection to a machine running the NeXTstep windowing + system. Not currently implemented. +w32 A connection to a machine running Microsoft Windows NT or + Windows 95. +pc A direct-write MS-DOS frame. Not currently implemented. + +PROPS should be a plist of properties, as in the call to `make-frame'. + +If a connection to CONNECTION already exists, it is reused; otherwise, +a new connection is opened." + (make-frame props (make-device type connection props))) + +;; Alias, kept temporarily. +(defalias 'new-frame 'make-frame) + +; FSFmacs has make-frame here. We have it in C, so no need for +; frame-creation-function. + +(defun filtered-frame-list (predicate &optional device) + "Return a list of all live frames which satisfy PREDICATE. +If optional second arg DEVICE is non-nil, restrict the frames + returned to that device." + (let ((frames (if device (device-frame-list device) + (frame-list))) + good-frames) + (while (consp frames) + (if (funcall predicate (car frames)) + (setq good-frames (cons (car frames) good-frames))) + (setq frames (cdr frames))) + good-frames)) + +(defun minibuffer-frame-list (&optional device) + "Return a list of all frames with their own minibuffers. +If optional second arg DEVICE is non-nil, restrict the frames + returned to that device." + (filtered-frame-list + #'(lambda (frame) + (eq frame (window-frame (minibuffer-window frame)))) + device)) + +(defun frame-minibuffer-only-p (frame) + "Return non-nil if FRAME is a minibuffer-only frame." + (eq (frame-root-window frame) (minibuffer-window frame))) + +(defun frame-remove-geometry-props (plist) + "Return the property list PLIST, but with geometry specs removed. +This deletes all bindings in PLIST for `top', `left', `width', +`height', `user-size' and `user-position' properties. +Emacs uses this to avoid overriding explicit moves and resizings from +the user during startup." + (setq plist (canonicalize-lax-plist (copy-sequence plist))) + (mapcar #'(lambda (propname) + (if (lax-plist-member plist propname) + (progn + (setq frame-initial-geometry-arguments + (cons propname + (cons (lax-plist-get plist propname) + frame-initial-geometry-arguments))) + (setq plist (lax-plist-remprop plist propname))))) + '(height width top left user-size user-position)) + plist) + +(defun other-frame (arg) + "Select the ARG'th different visible frame, and raise it. +All frames are arranged in a cyclic order. +This command selects the frame ARG steps away in that order. +A negative ARG moves in the opposite order." + (interactive "p") + (let ((frame (selected-frame))) + (while (> arg 0) + (setq frame (next-frame frame 'visible-nomini)) + (setq arg (1- arg))) + (while (< arg 0) + (setq frame (previous-frame frame 'visible-nomini)) + (setq arg (1+ arg))) + (raise-frame frame) + (select-frame frame) + ;this is a bad idea; you should in general never warp the + ;pointer unless the user asks for this. Furthermore, + ;our version of `set-mouse-position' takes a window, + ;not a frame. + ;(set-mouse-position (selected-frame) (1- (frame-width)) 0) + ;some weird FSFmacs randomness + ;(if (fboundp 'unfocus-frame) + ; (unfocus-frame)))) + )) + +;; XEmacs-added utility functions + +; this is in C in FSFmacs +(defun frame-list () + "Return a list of all frames on all devices/consoles." + ;; Lists are copies, so nconc is safe here. + (apply 'nconc (mapcar 'device-frame-list (device-list)))) + +(defun frame-type (&optional frame) + "Return the type of the specified frame (e.g. `x' or `tty'). +This is equivalent to the type of the frame's device. +Value is `tty' for a tty frame (a character-only terminal), +`x' for a frame that is an X window, +`ns' for a frame that is a NeXTstep window (not yet implemented), +`win32' for a frame that is a Windows or Windows NT window (not yet + implemented), +`pc' for a frame that is a direct-write MS-DOS frame (not yet implemented), +`stream' for a stream frame (which acts like a stdio stream), and +`dead' for a deleted frame." + (or frame (setq frame (selected-frame))) + (if (not (frame-live-p frame)) 'dead + (device-type (frame-device frame)))) + +(defun device-or-frame-p (object) + "Return non-nil if OBJECT is a device or frame." + (or (devicep object) + (framep object))) + +(defun device-or-frame-type (device-or-frame) + "Return the type (e.g. `x' or `tty') of DEVICE-OR-FRAME. +DEVICE-OR-FRAME should be a device or a frame object. See `device-type' +for a description of the possible types." + (if (devicep device-or-frame) + (device-type device-or-frame) + (frame-type device-or-frame))) + +(defun fw-frame (obj) + "Given a frame or window, return the associated frame. +Return nil otherwise." + (cond ((windowp obj) (window-frame obj)) + ((framep obj) obj) + (t nil))) + + +;;;; Frame configurations + +(defun current-frame-configuration () + "Return a list describing the positions and states of all frames. +Its car is `frame-configuration'. +Each element of the cdr is a list of the form (FRAME PLIST WINDOW-CONFIG), +where + FRAME is a frame object, + PLIST is a property list specifying some of FRAME's properties, and + WINDOW-CONFIG is a window configuration object for FRAME." + (cons 'frame-configuration + (mapcar (function + (lambda (frame) + (list frame + (frame-properties frame) + (current-window-configuration frame)))) + (frame-list)))) + +(defun set-frame-configuration (configuration &optional nodelete) + "Restore the frames to the state described by CONFIGURATION. +Each frame listed in CONFIGURATION has its position, size, window +configuration, and other properties set as specified in CONFIGURATION. +Ordinarily, this function deletes all existing frames not +listed in CONFIGURATION. But if optional second argument NODELETE +is given and non-nil, the unwanted frames are iconified instead." + (or (frame-configuration-p configuration) + (signal 'wrong-type-argument + (list 'frame-configuration-p configuration))) + (let ((config-plist (cdr configuration)) + frames-to-delete) + (mapc (lambda (frame) + (let ((properties (assq frame config-plist))) + (if properties + (progn + (set-frame-properties + frame + ;; Since we can't set a frame's minibuffer status, + ;; we might as well omit the parameter altogether. + (lax-plist-remprop (nth 1 properties) 'minibuffer)) + (set-window-configuration (nth 2 properties))) + (setq frames-to-delete (cons frame frames-to-delete))))) + (frame-list)) + (if nodelete + ;; Note: making frames invisible here was tried + ;; but led to some strange behavior--each time the frame + ;; was made visible again, the window manager asked afresh + ;; for where to put it. + (mapc 'iconify-frame frames-to-delete) + (mapc 'delete-frame frames-to-delete)))) + +; this function is in subr.el in FSFmacs. +; that's because they don't always include frame.el, while we do. + +(defun frame-configuration-p (object) + "Return non-nil if OBJECT seems to be a frame configuration. +Any list whose car is `frame-configuration' is assumed to be a frame +configuration." + (and (consp object) + (eq (car object) 'frame-configuration))) + + +;; FSFmacs has functions `frame-width', `frame-height' here. +;; We have them in C. + +;; FSFmacs has weird functions `set-default-font', `set-background-color', +;; `set-foreground-color' here. They don't do sensible things like +;; set faces; instead they set frame properties (??!!) and call +;; useless functions such as `frame-update-faces' and +;; `frame-update-face-colors'. + +;; FSFmacs has functions `set-cursor-color', `set-mouse-color', and +;; `set-border-color', which refer to frame properties. +;; #### We need to use specifiers here. + +;(defun auto-raise-mode (arg) +; "Toggle whether or not the selected frame should auto-raise. +;With arg, turn auto-raise mode on if and only if arg is positive. +;Note that this controls Emacs's own auto-raise feature. +;Some window managers allow you to enable auto-raise for certain windows. +;You can use that for Emacs windows if you wish, but if you do, +;that is beyond the control of Emacs and this command has no effect on it." +; (interactive "P") +; (if (null arg) +; (setq arg +; (if (frame-property (selected-frame) 'auto-raise) +; -1 1))) +; (set-frame-property (selected-frame) 'auto-raise (> arg 0))) + +;(defun auto-lower-mode (arg) +; "Toggle whether or not the selected frame should auto-lower. +;With arg, turn auto-lower mode on if and only if arg is positive. +;Note that this controls Emacs's own auto-lower feature. +;Some window managers allow you to enable auto-lower for certain windows. +;You can use that for Emacs windows if you wish, but if you do, +;that is beyond the control of Emacs and this command has no effect on it." +; (interactive "P") +; (if (null arg) +; (setq arg +; (if (frame-property (selected-frame) 'auto-lower) +; -1 1))) +; (set-frame-property (selected-frame) 'auto-lower (> arg 0))) + +;; FSFmacs has silly functions `toggle-scroll-bar', +;; `toggle-horizontal-scrollbar' + +;;; Iconifying emacs. +;;; +;;; The function iconify-emacs replaces every non-iconified emacs window +;;; with a *single* icon. Iconified emacs windows are left alone. When +;;; emacs is in this globally-iconified state, de-iconifying any emacs icon +;;; will uniconify all frames that were visible, and iconify all frames +;;; that were not. This is done by temporarily changing the value of +;;; `map-frame-hook' to `deiconify-emacs' (which should never be called +;;; except from the map-frame-hook while emacs is iconified). +;;; +;;; The title of the icon representing all emacs frames is controlled by +;;; the variable `icon-name'. This is done by temporarily changing the +;;; value of `frame-icon-title-format'. Unfortunately, this changes the +;;; titles of all emacs icons, not just the "big" icon. +;;; +;;; It would be nice if existing icons were removed and restored by +;;; iconifying the emacs process, but I couldn't make that work yet. + +(defvar icon-name nil) ; set this at run time, not load time. + +(defvar iconification-data nil) + +(defun iconify-emacs () + "Replace every non-iconified FRAME with a *single* icon. +Iconified frames are left alone. When XEmacs is in this +globally-iconified state, de-iconifying any emacs icon will uniconify +all frames that were visible, and iconify all frames that were not." + (interactive) + (if iconification-data (error "already iconified?")) + (let* ((frames (frame-list)) + (rest frames) + (me (selected-frame)) + frame) + (while rest + (setq frame (car rest)) + (setcar rest (cons frame (frame-visible-p frame))) +; (if (memq (cdr (car rest)) '(icon nil)) +; (progn +; (make-frame-visible frame) ; deiconify, and process the X event +; (sleep-for 500 t) ; process X events; I really want to XSync() here +; )) + (or (eq frame me) (make-frame-invisible frame)) + (setq rest (cdr rest))) + (or (boundp 'map-frame-hook) (setq map-frame-hook nil)) + (or icon-name + (setq icon-name (concat invocation-name " @ " (system-name)))) + (setq iconification-data + (list frame-icon-title-format map-frame-hook frames) + frame-icon-title-format icon-name + map-frame-hook 'deiconify-emacs) + (iconify-frame me))) + + +(defun deiconify-emacs (&optional ignore) + (or iconification-data (error "not iconified?")) + (setq frame-icon-title-format (car iconification-data) + map-frame-hook (car (cdr iconification-data)) + iconification-data (car (cdr (cdr iconification-data)))) + (while iconification-data + (let ((visibility (cdr (car iconification-data)))) + (cond (visibility ;; JV (Note non-nil means visible in XEmacs) + (make-frame-visible (car (car iconification-data)))) +; (t ;; (eq visibility 'icon) ;; JV Not in XEmacs!!! +; (make-frame-visible (car (car iconification-data))) +; (sleep-for 500 t) ; process X events; I really want to XSync() here +; (iconify-frame (car (car iconification-data)))) + ;; (t nil) + )) + (setq iconification-data (cdr iconification-data)))) + +(defun suspend-or-iconify-emacs () + "Calls iconify-emacs if frame is an X frame, otherwise calls suspend-emacs" + (interactive) + (cond + ((eq (frame-type) 'x) + (iconify-emacs)) + ((and (eq (frame-type) 'tty) + (console-tty-controlling-process (selected-console))) + (suspend-console (selected-console))) + (t + (suspend-emacs)))) + +;; This is quite a mouthful, but it should be descriptive, as it's +;; bound to C-z +(defun suspend-emacs-or-iconify-frame () + "Iconify current frame if it is an X frame, otherwise suspend Emacs." + (interactive) + (cond ((eq (frame-type) 'x) + (iconify-frame)) + ((and (eq (frame-type) 'tty) + (console-tty-controlling-process (selected-console))) + (suspend-console (selected-console))) + (t + (suspend-emacs)))) + + +;;; auto-raise and auto-lower + +(defcustom auto-raise-frame nil + "*If true, frames will be raised to the top when selected. +Under X, most ICCCM-compliant window managers will have an option to do this +for you, but this variable is provided in case you're using a broken WM." + :type 'boolean + :group 'frames) + +(defcustom auto-lower-frame nil + "*If true, frames will be lowered to the bottom when no longer selected. +Under X, most ICCCM-compliant window managers will have an option to do this +for you, but this variable is provided in case you're using a broken WM." + :type 'boolean + :group 'frames) + +(defun default-select-frame-hook () + "Implements the `auto-raise-frame' variable. +For use as the value of `select-frame-hook'." + (if auto-raise-frame (raise-frame (selected-frame)))) + +(defun default-deselect-frame-hook () + "Implements the `auto-lower-frame' variable. +For use as the value of `deselect-frame-hook'." + (if auto-lower-frame (lower-frame (selected-frame)))) + +(or select-frame-hook + (add-hook 'select-frame-hook 'default-select-frame-hook)) + +(or deselect-frame-hook + (add-hook 'deselect-frame-hook 'default-deselect-frame-hook)) + +(defun default-drag-and-drop-functions (frame filepath &optional data) + "Implements the `drag-and-drop-functions' variable. +For use as the value of `drag-and-drop-functions'. +A file is popped up in a new buffer, some data without +is inserted at point." + ;; changed this back -- hope it works for CDE ;-) Oliver Graf + ;; the OffiX drop stuff has moved to mouse.el (mouse-offix-drop) + (if data + (insert data) + (let ((x pop-up-windows)) + (setq pop-up-windows nil) + (pop-to-buffer (find-file-noselect filepath) nil frame) + (make-frame-visible frame) + (setq pop-up-windows x)))) + +(and (boundp 'drag-and-drop-functions) + (or drag-and-drop-functions + (add-hook 'drag-and-drop-functions 'default-drag-and-drop-functions))) + +(defun cde-start-drag (begin end) + "Implements the CDE drag operation. +Calls the internal function cde-start-drag-internal to do the actual work." + (interactive "_r") + (if (featurep 'cde) + ;; Avoid build-time doc string warning by calling the function + ;; in the following roundabout way: + (funcall (intern "cde-start-drag-internal") + (buffer-substring-no-properties begin end)) + (error "CDE functionality not compiled in."))) + +;; the OffiX drag stuff will soon move also (perhaps mouse.el) +;; if the drag event is done +(defun offix-start-drag (event data &optional type) + "Implements the OffiX drag operation. +Calls the internal function offix-start-drag-internal to do the actual work. +If type is not given, DndText is assumed." + ;; Oliver Graf + (interactive "esi") + (if (featurep 'offix) + (funcall (intern "offix-start-drag-internal") event data type) + (error "OffiX functionality not compiled in."))) + +(defun offix-start-drag-region (event begin end) + "Implements the OffiX drag operation for a region. +Calls the internal function offix-start-drag-internal to do the actual work. +This always assumes DndText as type." + ;; Oliver Graf + (interactive "_er") + (if (featurep 'offix) + (funcall (intern "offix-start-drag-internal") + event (buffer-substring-no-properties begin end)) + (error "OffiX functionality not compiled in."))) + + + +;;; Application-specific frame-management + +(defvar get-frame-for-buffer-default-frame-name nil + "The default frame to select; see doc of `get-frame-for-buffer'.") + +(defvar get-frame-for-buffer-default-instance-limit nil) + +(defun get-frame-name-for-buffer (buffer) + (let ((mode (and (get-buffer buffer) + (save-excursion (set-buffer buffer) + major-mode)))) + (or (get mode 'frame-name) + get-frame-for-buffer-default-frame-name))) + +(defun get-frame-for-buffer-make-new-frame (buffer &optional frame-name plist) + (let* ((fr (make-frame plist)) + (w (frame-root-window fr))) + ;; + ;; Make the one buffer being displayed in this newly created + ;; frame be the buffer of interest, instead of something + ;; random, so that it won't be shown in two-window mode. + ;; Avoid calling switch-to-buffer here, since that's something + ;; people might want to call this routine from. + ;; + ;; (If the root window doesn't have a buffer, then that means + ;; there is more than one window on the frame, which can only + ;; happen if the user has done something funny on the frame- + ;; creation-hook. If that's the case, leave it alone.) + ;; + (if (window-buffer w) + (set-window-buffer w buffer)) + fr)) + +(defun get-frame-for-buffer-noselect (buffer + &optional not-this-window-p on-frame) + "Return a frame in which to display BUFFER. +This is a subroutine of `get-frame-for-buffer' (which see)." + (let (name limit) + (cond + ((or on-frame (eq (selected-window) (minibuffer-window))) + ;; don't switch frames if a frame was specified, or to list + ;; completions from the minibuffer, etc. + nil) + + ((setq name (get-frame-name-for-buffer buffer)) + ;; + ;; This buffer's mode expressed a preference for a frame of a particular + ;; name. That always takes priority. + ;; + (let ((limit (get name 'instance-limit)) + (defaults (get name 'frame-defaults)) + (matching-frames '()) + frames frame already-visible) + ;; Sort the list so that iconic frames will be found last. They + ;; will be used too, but mapped frames take precedence. And + ;; fully visible frames come before occluded frames. + ;; Hidden frames come after really visible ones + (setq frames + (sort (frame-list) + #'(lambda (s1 s2) + (cond ((frame-totally-visible-p s2) + nil) + ((not (frame-visible-p s2)) + (frame-visible-p s1)) + ((eq (frame-visible-p s2) 'hidden) + (eq (frame-visible-p s1) t )) + ((not (frame-totally-visible-p s2)) + (and (frame-visible-p s1) + (frame-totally-visible-p s1))))))) + ;; but the selected frame should come first, even if it's occluded, + ;; to minimize thrashing. + (setq frames (cons (selected-frame) + (delq (selected-frame) frames))) + + (setq name (symbol-name name)) + (while frames + (setq frame (car frames)) + (if (equal name (frame-name frame)) + (if (get-buffer-window buffer frame) + (setq already-visible frame + frames nil) + (setq matching-frames (cons frame matching-frames)))) + (setq frames (cdr frames))) + (cond (already-visible + already-visible) + ((or (null matching-frames) + (eq limit 0) ; means create with reckless abandon + (and limit (< (length matching-frames) limit))) + (get-frame-for-buffer-make-new-frame + buffer + name + (alist-to-plist (acons 'name name + (plist-to-alist defaults))))) + (t + ;; do not switch any of the window/buffer associations in an + ;; existing frame; this function only picks a frame; the + ;; determination of which windows on it get reused is up to + ;; display-buffer itself. +;; (or (window-dedicated-p (selected-window)) +;; (switch-to-buffer buffer)) + (car matching-frames))))) + + ((setq limit get-frame-for-buffer-default-instance-limit) + ;; + ;; This buffer's mode did not express a preference for a frame of a + ;; particular name, but the user wants a new frame rather than + ;; reusing the existing one. + (let* ((defname + (or (plist-get default-frame-plist 'name) + default-frame-name)) + (frames + (sort (filtered-frame-list #'(lambda (x) + (or (frame-visible-p x) + (frame-iconified-p x)))) + #'(lambda (s1 s2) + (cond ((and (frame-visible-p s1) + (not (frame-visible-p s2)))) + ((and (eq (frame-visible-p s1) t) + (eq (frame-visible-p s2) 'hidden))) + ((and (frame-visible-p s2) + (not (frame-visible-p s1))) + nil) + ((and (equal (frame-name s1) defname) + (not (equal (frame-name s2) defname)))) + ((and (equal (frame-name s2) defname) + (not (equal (frame-name s1) defname))) + nil) + ((frame-totally-visible-p s2) + nil) + (t)))))) + ;; put the selected frame last. The user wants a new frame, + ;; so don't reuse the existing one unless forced to. + (setq frames (append (delq (selected-frame) frames) (list frames))) + (if (or (eq limit 0) ; means create with reckless abandon + (< (length frames) limit)) + (get-frame-for-buffer-make-new-frame buffer) + (car frames)))) + + (t + ;; + ;; This buffer's mode did not express a preference for a frame of a + ;; particular name. So try to find a frame already displaying this + ;; buffer. + ;; + (let ((w (or (get-buffer-window buffer 'visible) ; check visible first + (get-buffer-window buffer 0)))) ; then iconic + (cond ((null w) + ;; It's not in any window - return nil, meaning no frame has + ;; preference. + nil) + ((and not-this-window-p + (eq (selected-frame) (window-frame w))) + ;; It's in a window, but on this frame, and we have been + ;; asked to pick another window. Return nil, meaning no + ;; frame has preference. + nil) + (t + ;; Otherwise, return the frame of the buffer's window. + (window-frame w)))))))) + + +;; The pre-display-buffer-function is called for effect, so this needs to +;; actually select the frame it wants. Fdisplay_buffer() takes notice of +;; changes to the selected frame. +(defun get-frame-for-buffer (buffer &optional not-this-window-p on-frame) + "Select and return a frame in which to display BUFFER. +Normally, the buffer will simply be displayed in the current frame. +But if the symbol naming the major-mode of the buffer has a 'frame-name +property (which should be a symbol), then the buffer will be displayed in +a frame of that name. If there is no frame of that name, then one is +created. + +If the major-mode doesn't have a 'frame-name property, then the frame +named by `get-frame-for-buffer-default-frame-name' will be used. If +that is nil (the default) then the currently selected frame will used. + +If the frame-name symbol has an 'instance-limit property (an integer) +then each time a buffer of the mode in question is displayed, a new frame +with that name will be created, until there are `instance-limit' of them. +If instance-limit is 0, then a new frame will be created each time. + +If a buffer is already displayed in a frame, then `instance-limit' is +ignored, and that frame is used. + +If the frame-name symbol has a 'frame-defaults property, then that is +prepended to the `default-frame-plist' when creating a frame for the +first time. + +This function may be used as the value of `pre-display-buffer-function', +to cause the display-buffer function and its callers to exhibit the above +behavior." + (let ((frame (get-frame-for-buffer-noselect + buffer not-this-window-p on-frame))) + (if (not (eq frame (selected-frame))) + frame + (select-frame frame) + (or (frame-visible-p frame) + ;; If the frame was already visible, just focus on it. + ;; If it wasn't visible (it was just created, or it used + ;; to be iconified) then uniconify, raise, etc. + (make-frame-visible frame)) + frame))) + +(defun frames-of-buffer (&optional buffer visible-only) + "Return list of frames that BUFFER is currently being displayed on. +If the buffer is being displayed on the currently selected frame, that frame +is first in the list. VISIBLE-ONLY will only list non-iconified frames." + (let ((list (windows-of-buffer buffer)) + (cur-frame (selected-frame)) + next-frame frames save-frame) + + (while list + (if (memq (setq next-frame (window-frame (car list))) + frames) + nil + (if (eq cur-frame next-frame) + (setq save-frame next-frame) + (and + (or (not visible-only) + (frame-visible-p next-frame)) + (setq frames (append frames (list next-frame)))))) + (setq list (cdr list))) + + (if save-frame + (append (list save-frame) frames) + frames))) + +(defcustom temp-buffer-shrink-to-fit nil + "*When non-nil resize temporary output buffers to minimize blank lines." + :type 'boolean + :group 'frames) + +(defcustom temp-buffer-max-height .5 + "*Proportion of frame to use for temp windows." + :type 'number + :group 'frames) + +(defun show-temp-buffer-in-current-frame (buffer) + "For use as the value of temp-buffer-show-function: +always displays the buffer in the current frame, regardless of the behavior +that would otherwise be introduced by the `pre-display-buffer-function', which +is normally set to `get-frame-for-buffer' (which see)." + (let ((pre-display-buffer-function nil)) ; turn it off, whatever it is + (let ((window (display-buffer buffer))) + (if (not (eq (last-nonminibuf-frame) (window-frame window))) + ;; only the pre-display-buffer-function should ever do this. + (error "display-buffer switched frames on its own!!")) + (setq minibuffer-scroll-window window) + (set-window-start window 1) ; obeys narrowing + (set-window-point window 1) + (when temp-buffer-shrink-to-fit + (let* ((temp-window-size (round (* temp-buffer-max-height + (frame-height (window-frame window))))) + (size (window-displayed-height window))) + (when (< size temp-window-size) + (enlarge-window (- temp-window-size size) nil window))) + (shrink-window-if-larger-than-buffer window)) + nil))) + +(setq pre-display-buffer-function 'get-frame-for-buffer) +(setq temp-buffer-show-function 'show-temp-buffer-in-current-frame) + + +;; from Bob Weiner , modified by Ben Wing +(defun delete-other-frames (&optional frame) + "Delete all but FRAME (or the selected frame)." + (interactive) + (mapc 'delete-frame (delq (or frame (selected-frame)) (frame-list)))) + +;; By adding primitives to directly access the window hierarchy, +;; we can move many functions into Lisp. We do it this way +;; because the implementations are simpler in Lisp, and because +;; new functions like this can be added without requiring C +;; additions. + +(defun frame-utmost-window-2 (window position left-right-p major-end-p + minor-end-p) + ;; LEFT-RIGHT-P means we're looking for the leftmost or rightmost + ;; window, instead of the highest or lowest. In this case, we + ;; say that the "major axis" goes left-to-right instead of top-to- + ;; bottom. The "minor axis" always goes perpendicularly. + ;; + ;; If MAJOR-END-P is t, we're looking for a windows that abut the + ;; end (i.e. right or bottom) of the major axis, instead of the + ;; start. + ;; + ;; If MINOR-END-P is t, then we want to start counting from the + ;; end of the minor axis instead of the beginning. + ;; + ;; Here's the general idea: Imagine we're trying to count the number + ;; of windows that abut the top; call this function foo(). So, we + ;; start with the root window. If this is a vertical combination + ;; window, then foo() applied to the root window is the same as + ;; foo() applied to the first child. If the root is a horizontal + ;; combination window, then foo() applied to the root is the + ;; same as the sum of foo() applied to each of the children. + ;; Otherwise, the root window is a leaf window, and foo() is 1. + ;; Now it's clear that, each time foo() encounters a leaf window, + ;; it's encountering a different window that abuts the top. + ;; With a little examining, you can see that foo encounters the + ;; top-abutting windows in order from left to right. We can + ;; modify foo() to return the nth top-abutting window by simply + ;; keeping a global variable that is decremented each time + ;; foo() encounters a leaf window and would return 1. If the + ;; global counter gets to zero, we've encountered the window + ;; we were looking for, so we exit right away using a `throw'. + ;; Otherwise, we make sure that all normal paths return nil. + + (let (child) + (cond ((setq child (if left-right-p + (window-first-hchild window) + (window-first-vchild window))) + (if major-end-p + (while (window-next-child child) + (setq child (window-next-child child)))) + (frame-utmost-window-2 child position left-right-p major-end-p + minor-end-p)) + ((setq child (if left-right-p + (window-first-vchild window) + (window-first-hchild window))) + (if minor-end-p + (while (window-next-child child) + (setq child (window-next-child child)))) + (while child + (frame-utmost-window-2 child position left-right-p major-end-p + minor-end-p) + (setq child (if minor-end-p + (window-previous-child child) + (window-next-child child)))) + nil) + (t + (setcar position (1- (car position))) + (if (= (car position) 0) + (throw 'fhw-exit window) + nil))))) + +(defun frame-utmost-window-1 (frame position left-right-p major-end-p) + (let (minor-end-p) + (or frame (setq frame (selected-frame))) + (or position (setq position 0)) + (if (>= position 0) + (setq position (1+ position)) + (setq minor-end-p t) + (setq position (- position))) + (catch 'fhw-exit + ;; we use a cons here as a simple form of call-by-reference. + ;; scheme has "boxes" for the same purpose. + (frame-utmost-window-2 (frame-root-window frame) (list position) + left-right-p major-end-p minor-end-p)))) + + +(defun frame-highest-window (&optional frame position) + "Return the highest window on FRAME which is at POSITION. +If omitted, FRAME defaults to the currently selected frame. +POSITION is used to distinguish between multiple windows that abut + the top of the frame: 0 means the leftmost window abutting the + top of the frame, 1 the next-leftmost, etc. POSITION can also + be less than zero: -1 means the rightmost window abutting the + top of the frame, -2 the next-rightmost, etc. +If omitted, POSITION defaults to 0, i.e. the leftmost highest window. +If there is no window at the given POSITION, return nil." + (frame-utmost-window-1 frame position nil nil)) + +(defun frame-lowest-window (&optional frame position) + "Return the lowest window on FRAME which is at POSITION. +If omitted, FRAME defaults to the currently selected frame. +POSITION is used to distinguish between multiple windows that abut + the bottom of the frame: 0 means the leftmost window abutting the + bottom of the frame, 1 the next-leftmost, etc. POSITION can also + be less than zero: -1 means the rightmost window abutting the + bottom of the frame, -2 the next-rightmost, etc. +If omitted, POSITION defaults to 0, i.e. the leftmost lowest window. +If there is no window at the given POSITION, return nil." + (frame-utmost-window-1 frame position nil t)) + +(defun frame-leftmost-window (&optional frame position) + "Return the leftmost window on FRAME which is at POSITION. +If omitted, FRAME defaults to the currently selected frame. +POSITION is used to distinguish between multiple windows that abut + the left edge of the frame: 0 means the highest window abutting the + left edge of the frame, 1 the next-highest, etc. POSITION can also + be less than zero: -1 means the lowest window abutting the + left edge of the frame, -2 the next-lowest, etc. +If omitted, POSITION defaults to 0, i.e. the highest leftmost window. +If there is no window at the given POSITION, return nil." + (frame-utmost-window-1 frame position t nil)) + +(defun frame-rightmost-window (&optional frame position) + "Return the rightmost window on FRAME which is at POSITION. +If omitted, FRAME defaults to the currently selected frame. +POSITION is used to distinguish between multiple windows that abut + the right edge of the frame: 0 means the highest window abutting the + right edge of the frame, 1 the next-highest, etc. POSITION can also + be less than zero: -1 means the lowest window abutting the + right edge of the frame, -2 the next-lowest, etc. +If omitted, POSITION defaults to 0, i.e. the highest rightmost window. +If there is no window at the given POSITION, return nil." + (frame-utmost-window-1 frame position t t)) + + + +;; frame properties. + +(defun set-frame-property (frame prop val) + "Set property PROP of FRAME to VAL. See `set-frame-properties'." + (set-frame-properties frame (list prop val))) + +(defun frame-height (&optional frame) + "Return number of lines available for display on FRAME." + (frame-property frame 'height)) + +(defun frame-width (&optional frame) + "Return number of columns available for display on FRAME." + (frame-property frame 'width)) + +(put 'cursor-color 'frame-property-alias [text-cursor background]) +(put 'modeline 'frame-property-alias 'has-modeline-p) + + +(provide 'frame) + +;;; frame.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/glyphs.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/glyphs.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,684 @@ +;;; glyphs.el --- Lisp interface to C glyphs + +;; Copyright (C) 1994, 1997 Free Software Foundation, Inc. +;; Copyright (C) 1995, 1996 Ben Wing. + +;; Author: Chuck Thompson , Ben Wing +;; Maintainer: XEmacs Development Team +;; Keywords: extensions, internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; font specifiers + +(defun make-image-specifier (spec-list) + "Create a new `image' specifier object with the given specification list. +SPEC-LIST can be a list of specifications (each of which is a cons of a +locale and a list of instantiators), a single instantiator, or a list +of instantiators. See `make-specifier' for more information about +specifiers." + (make-specifier-and-init 'image spec-list)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; glyphs + +(defconst built-in-glyph-specifiers + '(image contrib-p baseline) + "A list of the built-in face properties that are specifiers.") + +(defun glyph-property (glyph property &optional locale) + "Return GLYPH's value of the given PROPERTY. + +If LOCALE is omitted, the GLYPH's actual value for PROPERTY will be + returned. For built-in properties, this will be a specifier object + of a type appropriate to the property (e.g. a font or color + specifier). For other properties, this could be anything. + +If LOCALE is supplied, then instead of returning the actual value, + the specification(s) for the given locale or locale type will + be returned. This will only work if the actual value of + PROPERTY is a specifier (this will always be the case for built-in + properties, but not or not may apply to user-defined properties). + If the actual value of PROPERTY is not a specifier, this value + will simply be returned regardless of LOCALE. + +The return value will be a list of instantiators (e.g. strings + specifying a font or color name), or a list of specifications, each + of which is a cons of a locale and a list of instantiators. + Specifically, if LOCALE is a particular locale (a buffer, window, + frame, device, or 'global), a list of instantiators for that locale + will be returned. Otherwise, if LOCALE is a locale type (one of + the symbols 'buffer, 'window, 'frame, 'device, 'device-class, or + 'device-type), the specifications for all locales of that type will + be returned. Finally, if LOCALE is 'all, the specifications for all + locales of all types will be returned. + +The specifications in a specifier determine what the value of + PROPERTY will be in a particular \"domain\" or set of circumstances, + which is typically a particular Emacs window along with the buffer + it contains and the frame and device it lies within. The value + is derived from the instantiator associated with the most specific + locale (in the order buffer, window, frame, device, and 'global) + that matches the domain in question. In other words, given a domain + (i.e. an Emacs window, usually), the specifier for PROPERTY will first + be searched for a specification whose locale is the buffer contained + within that window; then for a specification whose locale is the window + itself; then for a specification whose locale is the frame that the + window is contained within; etc. The first instantiator that is + valid for the domain (usually this means that the instantiator is + recognized by the device [i.e. the X server or TTY device] that the + domain is on. The function `glyph-property-instance' actually does + all this, and is used to determine how to display the glyph. + +See `set-glyph-property' for the built-in property-names." + (check-argument-type 'glyphp glyph) + (let ((value (get glyph property))) + (if (and locale + (or (memq property built-in-glyph-specifiers) + (specifierp value))) + (setq value (specifier-specs value locale))) + value)) + +(defun convert-glyph-property-into-specifier (glyph property) + "Convert PROPERTY on GLYPH into a specifier, if it's not already." + (check-argument-type 'glyphp glyph) + (let ((specifier (get glyph property))) + ;; if a user-property does not have a specifier but a + ;; locale was specified, put a specifier there. + ;; If there was already a value there, convert it to a + ;; specifier with the value as its 'global instantiator. + (if (not (specifierp specifier)) + (let ((new-specifier (make-specifier 'generic))) + (if (or (not (null specifier)) + ;; make sure the nil returned from `get' wasn't + ;; actually the value of the property + (null (get glyph property t))) + (add-spec-to-specifier new-specifier specifier)) + (setq specifier new-specifier) + (put glyph property specifier))))) + +(defun glyph-property-instance (glyph property + &optional domain default no-fallback) + "Return the instance of GLYPH's PROPERTY in the specified DOMAIN. + +Under most circumstances, DOMAIN will be a particular window, + and the returned instance describes how the specified property + actually is displayed for that window and the particular buffer + in it. Note that this may not be the same as how the property + appears when the buffer is displayed in a different window or + frame, or how the property appears in the same window if you + switch to another buffer in that window; and in those cases, + the returned instance would be different. + +DOMAIN defaults to the selected window if omitted. + +DOMAIN can be a frame or device, instead of a window. The value + returned for a such a domain is used in special circumstances + when a more specific domain does not apply; for example, a frame + value might be used for coloring a toolbar, which is conceptually + attached to a frame rather than a particular window. The value + is also useful in determining what the value would be for a + particular window within the frame or device, if it is not + overridden by a more specific specification. + +If PROPERTY does not name a built-in property, its value will + simply be returned unless it is a specifier object, in which case + it will be instanced using `specifier-instance'. + +Optional arguments DEFAULT and NO-FALLBACK are the same as in + `specifier-instance'." + (check-argument-type 'glyphp glyph) + (let ((value (get glyph property))) + (if (specifierp value) + (setq value (specifier-instance value domain default no-fallback))) + value)) + +(defun set-glyph-property (glyph property value &optional locale tag-set + how-to-add) + "Change a property of a GLYPH. + +NOTE: If you want to remove a property from a glyph, use + `remove-glyph-property' rather than attempting to set a value of nil + for the property. + +For built-in properties, the actual value of the property is a + specifier and you cannot change this; but you can change the + specifications within the specifier, and that is what this function + will do. For user-defined properties, you can use this function + to either change the actual value of the property or, if this value + is a specifier, change the specifications within it. + +If PROPERTY is a built-in property, the specifications to be added to + this property can be supplied in many different ways: + + -- If VALUE is a simple instantiator (e.g. a string naming a font or + color) or a list of instantiators, then the instantiator(s) will + be added as a specification of the property for the given LOCALE + (which defaults to 'global if omitted). + -- If VALUE is a list of specifications (each of which is a cons of + a locale and a list of instantiators), then LOCALE must be nil + (it does not make sense to explicitly specify a locale in this + case), and specifications will be added as given. + -- If VALUE is a specifier (as would be returned by `glyph-property' + if no LOCALE argument is given), then some or all of the + specifications in the specifier will be added to the property. + In this case, the function is really equivalent to + `copy-specifier' and LOCALE has the same semantics (if it is + a particular locale, the specification for the locale will be + copied; if a locale type, specifications for all locales of + that type will be copied; if nil or 'all, then all + specifications will be copied). + +HOW-TO-ADD should be either nil or one of the symbols 'prepend, + 'append, 'remove-tag-set-prepend, 'remove-tag-set-append, 'remove-locale, + 'remove-locale-type, or 'remove-all. See `copy-specifier' and + `add-spec-to-specifier' for a description of what each of + these means. Most of the time, you do not need to worry about + this argument; the default behavior usually is fine. + +In general, it is OK to pass an instance object (e.g. as returned + by `glyph-property-instance') as an instantiator in place of + an actual instantiator. In such a case, the instantiator used + to create that instance object will be used (for example, if + you set a font-instance object as the value of the 'font + property, then the font name used to create that object will + be used instead). If some cases, however, doing this + conversion does not make sense, and this will be noted in + the documentation for particular types of instance objects. + +If PROPERTY is not a built-in property, then this function will + simply set its value if LOCALE is nil. However, if LOCALE is + given, then this function will attempt to add VALUE as the + instantiator for the given LOCALE, using `add-spec-to-specifier'. + If the value of the property is not a specifier, it will + automatically be converted into a 'generic specifier. + + +The following symbols have predefined meanings: + + image The image used to display the glyph. + + baseline Percent above baseline that glyph is to be + displayed. + + contrib-p Whether the glyph contributes to the + height of the line it's on. + + face Face of this glyph (*not* a specifier)." + (check-argument-type 'glyphp glyph) + (if (memq property built-in-glyph-specifiers) + (set-specifier (get glyph property) value locale tag-set how-to-add) + + ;; This section adds user defined properties. + (if (not locale) + (put glyph property value) + (convert-glyph-property-into-specifier glyph property) + (add-spec-to-specifier (get glyph property) value locale tag-set + how-to-add))) + value) + +(defun remove-glyph-property (glyph property &optional locale tag-set exact-p) + "Remove a property from a glyph. +For built-in properties, this is analogous to `remove-specifier'. +See `remove-specifier' for the meaning of the LOCALE, TAG-SET, and EXACT-P + arguments." + (or locale (setq locale 'all)) + (if (memq property built-in-glyph-specifiers) + (remove-specifier (glyph-property glyph property) locale tag-set exact-p) + (if (eq locale 'all) + (remprop glyph property) + (convert-glyph-property-into-specifier glyph property) + (remove-specifier (glyph-property glyph property) locale tag-set + exact-p)))) + +(defun glyph-face (glyph) + "Return the face of GLYPH." + (glyph-property glyph 'face)) + +(defun set-glyph-face (glyph face) + "Change the face of GLYPH to FACE." +; (interactive (glyph-interactive "face")) + (set-glyph-property glyph 'face face)) + +(defun glyph-image (glyph &optional locale) + "Return the image of the given glyph, or nil if it is unspecified. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `glyph-property' for more information." + (glyph-property glyph 'image locale)) + +(defun glyph-image-instance (glyph &optional domain default no-fallback) + "Return the instance of the given glyph's image in the given domain. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing how the image appears in that + particular window and buffer will be returned. + +See `glyph-property-instance' for more information." + (glyph-property-instance glyph 'image domain default no-fallback)) + +(defun set-glyph-image (glyph spec &optional locale tag-set how-to-add) + "Change the image of the given glyph. + +SPEC should be an instantiator (a string or vector; see + `image-specifier-p' for a description of possible values here), + a list of (possibly tagged) instantiators, an alist of specifications + (each mapping a locale to an instantiator list), or an image specifier + object. + +If SPEC is an alist, LOCALE must be omitted. If SPEC is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-glyph-property' for more information." + ; (interactive (glyph-interactive "image")) + (set-glyph-property glyph 'image spec locale tag-set how-to-add)) + +(defun glyph-contrib-p (glyph &optional locale) + "Return whether GLYPH contributes to its line height. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `glyph-property' for more information." + (glyph-property glyph 'contrib-p locale)) + +(defun glyph-contrib-p-instance (glyph &optional domain default no-fallback) + "Return the instance of the GLYPH's 'contrib-p property in the given domain. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an instance object describing what the 'contrib-p property is in + that particular window and buffer will be returned. + +See `glyph-property-instance' for more information." + (glyph-property-instance glyph 'contrib-p domain default no-fallback)) + +(defun set-glyph-contrib-p (glyph spec &optional locale tag-set how-to-add) + "Change the contrib-p of the given glyph. + +SPEC should be an instantiator (t or nil), a list of (possibly + tagged) instantiators, an alist of specifications (each mapping a + locale to an instantiator list), or a boolean specifier object. + +If SPEC is an alist, LOCALE must be omitted. If SPEC is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-glyph-property' for more information." + ; (interactive (glyph-interactive "contrib-p")) + (set-glyph-property glyph 'contrib-p spec locale tag-set how-to-add)) + +(defun glyph-baseline (glyph &optional locale) + "Return the baseline of the given glyph, or nil if it is unspecified. + +LOCALE may be a locale (the instantiators for that particular locale + will be returned), a locale type (the specifications for all locales + of that type will be returned), 'all (all specifications will be + returned), or nil (the actual specifier object will be returned). + +See `glyph-property' for more information." + (glyph-property glyph 'baseline locale)) + +(defun glyph-baseline-instance (glyph &optional domain default no-fallback) + "Return the instance of the given glyph's baseline in the given domain. + +Normally DOMAIN will be a window or nil (meaning the selected window), + and an integer or nil (specifying the baseline in that particular + window and buffer) will be returned. + +See `glyph-property-instance' for more information." + (glyph-property-instance glyph 'baseline domain default no-fallback)) + +(defun set-glyph-baseline (glyph spec &optional locale tag-set how-to-add) + "Change the baseline of the given glyph. + +SPEC should be an instantiator (an integer [a percentage above the + baseline of the line the glyph is on] or nil), a list of (possibly + tagged) instantiators, an alist of specifications (each mapping a + locale to an instantiator list), or a generic specifier object. + +If SPEC is an alist, LOCALE must be omitted. If SPEC is a + specifier object, LOCALE can be a locale, a locale type, 'all, + or nil; see `copy-specifier' for its semantics. Otherwise LOCALE + specifies the locale under which the specified instantiator(s) + will be added, and defaults to 'global. + +See `set-glyph-property' for more information." + ; (interactive (glyph-interactive "baseline")) + (set-glyph-property glyph 'baseline spec locale tag-set how-to-add)) + +(defun make-glyph (&optional spec-list type) + "Create a new `glyph' object of type TYPE. + +TYPE should be one of `buffer' (used for glyphs in an extent, the modeline, +the toolbar, or elsewhere in a buffer), `pointer' (used for the mouse-pointer), +or `icon' (used for a frame's icon), and defaults to `buffer'. + +SPEC-LIST is used to initialize the glyph's image. It is typically an +image instantiator (a string or a vector; see `image-specifier-p' for +a detailed description of the valid image instantiators), but can also +be a list of such instantiators (each one in turn is tried until an +image is successfully produced), a cons of a locale (frame, buffer, etc.) +and an instantiator, a list of such conses, or any other form accepted +by `canonicalize-spec-list'. See `make-specifier' for more information +about specifiers." + (let ((glyph (make-glyph-internal type))) + (and spec-list (set-glyph-image glyph spec-list)) + glyph)) + +(defun buffer-glyph-p (object) + "t if OBJECT is a glyph of type `buffer'." + (and (glyphp object) (eq 'buffer (glyph-type object)))) + +(defun pointer-glyph-p (object) + "t if OBJECT is a glyph of type `pointer'." + (and (glyphp object) (eq 'pointer (glyph-type object)))) + +(defun icon-glyph-p (object) + "t if OBJECT is a glyph of type `icon'." + (and (glyphp object) (eq 'icon (glyph-type object)))) + +(defun make-pointer-glyph (&optional spec-list) + "Create a new `pointer-glyph' object with the given specification list. + +This is equivalent to calling `make-glyph' and specifying a type of +`pointer'. + +SPEC-LIST is used to initialize the glyph's image. It is typically an +image instantiator (a string or a vector; see `image-specifier-p' for +a detailed description of the valid image instantiators), but can also +be a list of such instantiators (each one in turn is tried until an +image is successfully produced), a cons of a locale (frame, buffer, etc.) +and an instantiator, a list of such conses, or any other form accepted +by `canonicalize-spec-list'. See `make-specifier' for more information +about specifiers. + +You can also create a glyph with an empty SPEC-LIST and add image +instantiators afterwards using `set-glyph-image'." + (make-glyph spec-list 'pointer)) + +(defun make-icon-glyph (&optional spec-list) + "Create a new `icon-glyph' object with the given specification list. + +This is equivalent to calling `make-glyph' and specifying a type of +`icon'. + +SPEC-LIST is used to initialize the glyph's image. It is typically an +image instantiator (a string or a vector; see `image-specifier-p' for +a detailed description of the valid image instantiators), but can also +be a list of such instantiators (each one in turn is tried until an +image is successfully produced), a cons of a locale (frame, buffer, etc.) +and an instantiator, a list of such conses, or any other form accepted +by `canonicalize-spec-list'. See `make-specifier' for more information +about specifiers. + +You can also create a glyph with an empty SPEC-LIST and add image +instantiators afterwards using `set-glyph-image'." + (make-glyph spec-list 'icon)) + +(defun nothing-image-instance-p (object) + "t if OBJECT is an image instance of type `nothing'." + (and (image-instance-p object) (eq 'nothing (image-instance-type object)))) + +(defun text-image-instance-p (object) + "t if OBJECT is an image instance of type `text'." + (and (image-instance-p object) (eq 'text (image-instance-type object)))) + +(defun mono-pixmap-image-instance-p (object) + "t if OBJECT is an image instance of type `mono-pixmap'." + (and (image-instance-p object) (eq 'mono-pixmap + (image-instance-type object)))) + +(defun color-pixmap-image-instance-p (object) + "t if OBJECT is an image instance of type `color-pixmap'." + (and (image-instance-p object) (eq 'color-pixmap + (image-instance-type object)))) + +(defun pointer-image-instance-p (object) + "t if OBJECT is an image instance of type `pointer'." + (and (image-instance-p object) (eq 'pointer (image-instance-type object)))) + +(defun subwindow-image-instance-p (object) + "t if OBJECT is an image instance of type `subwindow'. +Subwindows are not implemented in this version of XEmacs." + (and (image-instance-p object) (eq 'subwindow (image-instance-type object)))) + +;;;;;;;;;; the built-in glyphs + +(defvar text-pointer-glyph (make-pointer-glyph) + "*The shape of the mouse-pointer when over text. +This is a glyph; use `set-glyph-image' to change it.") +(set-glyph-face text-pointer-glyph 'pointer) + +(defvar nontext-pointer-glyph (make-pointer-glyph) + "*The shape of the mouse-pointer when over a buffer, but not over text. +This is a glyph; use `set-glyph-image' to change it. +If unspecified in a particular domain, `text-pointer-glyph' is used.") +(set-glyph-face nontext-pointer-glyph 'pointer) + +(defvar modeline-pointer-glyph (make-pointer-glyph) + "*The shape of the mouse-pointer when over the modeline. +This is a glyph; use `set-glyph-image' to change it. +If unspecified in a particular domain, `nontext-pointer-glyph' is used.") +(set-glyph-face modeline-pointer-glyph 'pointer) + +(defvar selection-pointer-glyph (make-pointer-glyph) + "*The shape of the mouse-pointer when over a selectable text region. +This is a glyph; use `set-glyph-image' to change it. +If unspecified in a particular domain, `text-pointer-glyph' is used.") +(set-glyph-face selection-pointer-glyph 'pointer) + +(defvar busy-pointer-glyph (make-pointer-glyph) + "*The shape of the mouse-pointer when XEmacs is busy. +This is a glyph; use `set-glyph-image' to change it. +If unspecified in a particular domain, the pointer is not changed +when XEmacs is busy.") +(set-glyph-face busy-pointer-glyph 'pointer) + +(defvar toolbar-pointer-glyph (make-pointer-glyph) + "*The shape of the mouse-pointer when over a toolbar. +This is a glyph; use `set-glyph-image' to change it. +If unspecified in a particular domain, `nontext-pointer-glyph' is used.") +(set-glyph-face toolbar-pointer-glyph 'pointer) + +;; The following three are in C. +(if (featurep 'menubar) + (set-glyph-face menubar-pointer-glyph 'pointer)) +(if (featurep 'scrollbar) + (set-glyph-face scrollbar-pointer-glyph 'pointer)) +(set-glyph-face gc-pointer-glyph 'pointer) + +;; Now add the magic access/set behavior. + +(defun dontusethis-set-value-glyph-handler (sym args fun harg handler) + (error "Use `set-glyph-image' to set `%s'" sym)) +(defun dontusethis-make-unbound-glyph-handler (sym args fun harg handler) + (error "Can't `makunbound' `%s'" sym)) +(defun dontusethis-make-local-glyph-handler (sym args fun harg handler) + (error "Use `set-glyph-image' to make local values for `%s'" sym)) + +(defun define-constant-glyph (sym) + (dontusethis-set-symbol-value-handler + sym 'set-value + 'dontusethis-set-value-glyph-handler) + (dontusethis-set-symbol-value-handler + sym 'make-unbound + 'dontusethis-make-unbound-glyph-handler) + (dontusethis-set-symbol-value-handler + sym 'make-local + 'dontusethis-make-local-glyph-handler) + ;; Make frame properties magically work with glyph variables. + (put sym 'const-glyph-variable t)) + +(define-constant-glyph 'text-pointer-glyph) +(define-constant-glyph 'nontext-pointer-glyph) +(define-constant-glyph 'modeline-pointer-glyph) +(define-constant-glyph 'selection-pointer-glyph) +(define-constant-glyph 'busy-pointer-glyph) +(define-constant-glyph 'gc-pointer-glyph) +(define-constant-glyph 'toolbar-pointer-glyph) +(define-constant-glyph 'menubar-pointer-glyph) +(define-constant-glyph 'scrollbar-pointer-glyph) + +(define-constant-glyph 'octal-escape-glyph) +(define-constant-glyph 'control-arrow-glyph) +(define-constant-glyph 'invisible-text-glyph) +(define-constant-glyph 'hscroll-glyph) +(define-constant-glyph 'truncation-glyph) +(define-constant-glyph 'continuation-glyph) + +(define-constant-glyph 'frame-icon-glyph) + +;; backwards compatibility garbage + +(defun dontusethis-old-pointer-shape-handler (sym args fun harg handler) + (let ((value (car args))) + (if (null value) + (remove-specifier harg 'global) + (set-glyph-image (symbol-value harg) value)))) + +;; It might or might not be garbage, but it's rude. Make these +;; 'compatible instead of 'obsolete. -slb +(defun define-obsolete-pointer-glyph (old new) + (define-compatible-variable-alias old new) + (dontusethis-set-symbol-value-handler + old 'set-value 'dontusethis-old-pointer-shape-handler new)) + +;;; (defvar x-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-pointer-shape 'text-pointer-glyph) + +;;; (defvar x-nontext-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-nontext-pointer-shape 'nontext-pointer-glyph) + +;;; (defvar x-mode-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-mode-pointer-shape 'modeline-pointer-glyph) + +;;; (defvar x-selection-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-selection-pointer-shape + 'selection-pointer-glyph) + +;;; (defvar x-busy-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-busy-pointer-shape 'busy-pointer-glyph) + +;;; (defvar x-gc-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-gc-pointer-shape 'gc-pointer-glyph) + +;;; (defvar x-toolbar-pointer-shape nil) +(define-obsolete-pointer-glyph 'x-toolbar-pointer-shape 'toolbar-pointer-glyph) + +;;;;;;;;;; initialization + +(defun init-glyphs () + ;; initialize default image types + (if (featurep 'x) + (set-console-type-image-conversion-list 'x + `(,@(if (featurep 'xpm) '(("\\.xpm\\'" [xpm :file nil] 2))) + ("\\.xbm\\'" [xbm :file nil] 2) + ,@(if (featurep 'xpm) '(("\\`/\\* XPM \\*/" [xpm :data nil] 2))) + ,@(if (featurep 'xface) '(("\\`X-Face:" [xface :data nil] 2))) + ,@(if (featurep 'gif) '(("\\.gif\\'" [gif :file nil] 2) + ("\\`GIF8[79]" [gif :data nil] 2))) + ,@(if (featurep 'jpeg) '(("\\.jpe?g\\'" [jpeg :file nil] 2))) + ;; all of the JFIF-format JPEG's that I've seen begin with + ;; the following. I have no idea if this is standard. + ,@(if (featurep 'jpeg) '(("\\`\377\330\377\340\000\020JFIF" + [jpeg :data nil] 2))) + ,@(if (featurep 'png) '(("\\.png\\'" [png :file nil] 2))) + ,@(if (featurep 'png) '(("\\`\211PNG" [png :data nil] 2))) + ("" [autodetect :data nil] 2)))) + ;; #### this should really be formatted-string, not string but we + ;; don't have it implemented yet + ;; + ;; #define could also mean a bitmap as well as a version 1 XPM. Who + ;; cares. We don't want the file contents getting converted to a + ;; string in either case which is why the entry is there. + (if (featurep 'tty) + (progn + (set-console-type-image-conversion-list + 'tty + '(("^#define" [string :data "[xpm]"]) + ("\\`X-Face:" [string :data "[xface]"]) + ("\\`/\\* XPM \\*/" [string :data "[xpm]"]) + ("\\`GIF87" [string :data "[gif]"]) + ("\\`\377\330\340\000\020JFIF" [string :data "[jpeg]"]) + ("" [string :data nil] 2) + ;; this last one is here for pointers and icons and such -- + ;; strings are not allowed so they will be ignored. + ("" [nothing]))) + + ;; finish initializing truncation glyph -- created internally + ;; because it has a built-in bitmap + (set-glyph-image truncation-glyph "$" 'global 'tty) + + ;; finish initializing continuation glyph -- created internally + ;; because it has a built-in bitmap + (set-glyph-image continuation-glyph "\\" 'global 'tty) + + ;; finish initializing hscroll glyph -- created internally + ;; because it has a built-in bitmap + (set-glyph-image hscroll-glyph "$" 'global 'tty))) + + (set-glyph-image octal-escape-glyph "\\") + (set-glyph-image control-arrow-glyph "^") + (set-glyph-image invisible-text-glyph " ...") + ;; (set-glyph-image hscroll-glyph "$") + + ;; finish initializing xemacs logo -- created internally because it + ;; has a built-in bitmap + (if (featurep 'xpm) + (set-glyph-image xemacs-logo + (concat "../etc/" + (if emacs-beta-version + "xemacs-beta.xpm" + "xemacs.xpm")) + 'global 'x)) + (cond ((featurep 'xpm) + (set-glyph-image frame-icon-glyph + (concat "../etc/" "xemacs-icon.xpm") + 'global 'x)) + ((featurep 'x) + (set-glyph-image frame-icon-glyph + (concat "../etc/" "xemacs-icon2.xbm") + 'global 'x))) + + (if (featurep 'tty) + (set-glyph-image xemacs-logo + "XEmacs " + 'global 'tty)) +) + +(init-glyphs) + +;;; glyphs.el ends here. diff -r f427b8ec4379 -r 41ff10fd062f lisp/gui.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/gui.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,121 @@ +;;; gui.el --- Basic GUI functions for XEmacs. + +;; Copyright (C) 1997 Free Software Foundation, Inc. +;; Copyright (C) 1996 Ben Wing + +;; Maintainer: XEmacs Development Team +;; Keywords: internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: Not in FSF + +;;; Commentary: + +;; This file is dumped with XEmacs (when window system support is compiled in). + +;;; Code: + +(defcustom dialog-frame-plist '(width 60 height 20) + "Plist of frame properties for initially creating a dialog frame. +Properties specified here supersede the values given in +`default-frame-plist'." + :type '(repeat (group :inline t + (symbol :tag "Property") + (sexp :tag "Value"))) + :group 'frames) + +(defun make-dialog-frame (&optional props parent) + "Create a frame suitable for use as a dialog box. +The frame is made a child of PARENT (defaults to the selected frame), +and has additional properties PROPS, as well as `dialog-frame-plist'. +Normally it also has no modelines, menubars, or toolbars." + (or parent (setq parent (selected-frame))) + (let* ((ftop (frame-property parent 'top)) + (fleft (frame-property parent 'left)) + (fwidth (frame-pixel-width parent)) + (fheight (frame-pixel-height parent)) + (fonth (font-height (face-font 'default))) + (fontw (font-width (face-font 'default))) + (props (append props dialog-frame-plist)) + (dfheight (plist-get props 'height)) + (dfwidth (plist-get props 'width)) + ;; under FVWM at least, if I don't specify the initial position, + ;; it ends up always at (0, 0). xwininfo doesn't tell me + ;; that there are any program-specified position hints, so + ;; it must be an FVWM bug. So just be smashing and position + ;; in the center of the selected frame. + (frame (make-frame + (append props + `(popup ,parent initially-unmapped t + menubar-visible-p nil + has-modeline-p nil + default-toolbar-visible-p nil + modeline-shadow-thickness 0 + left ,(+ fleft (- (/ fwidth 2) + (/ (* dfwidth fontw) + 2))) + top ,(+ ftop (- (/ fheight 2) + (/ (* dfheight fonth) + 2)))))))) + (set-face-foreground 'modeline [default foreground] frame) + (set-face-background 'modeline [default background] frame) + (make-frame-visible frame) + frame)) + +(defvar gui-button-shadow-thickness 2) + +(defun gui-button-p (object) + "True if OBJECT is a GUI button." + (and (vectorp object) + (> (length object) 0) + (eq 'gui-button (aref object 0)))) + +(make-face 'gui-button-face "Face used for gui buttons") +(if (not (face-differs-from-default-p 'gui-button-face)) + (progn + (set-face-background 'gui-button-face "grey75") + (set-face-foreground 'gui-button-face "black"))) + +(defun make-gui-button (string &optional action user-data) + "Make a GUI button whose label is STRING and whose action is ACTION. +If the button is inserted in a buffer and then clicked on, and ACTION +is non-nil, ACTION will be called with one argument, USER-DATA." + (vector 'gui-button + (if (featurep 'xpm) + (xpm-button-create + string gui-button-shadow-thickness + (color-instance-name (face-foreground-instance 'gui-button-face)) + (color-instance-name (face-background-instance 'gui-button-face))) + (xbm-button-create string gui-button-shadow-thickness)) + action user-data)) + +(defun insert-gui-button (button &optional pos buffer) + "Insert GUI button BUTTON at POS in BUFFER." + (check-argument-type 'gui-button-p button) + (let ((annotation + (make-annotation (make-glyph (car (aref button 1))) + pos 'text buffer nil + (make-glyph (cadr (aref button 1))))) + (action (aref button 2))) + (and action + (progn + (set-annotation-action annotation action) + (set-annotation-data annotation (aref button 3)))))) + +;;; gui.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/help-nomule.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/help-nomule.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,105 @@ +;;; help-nomule.el --- Help functions when not in Mule + +;; Copyright (C) 1997 by Free Software Foundation, Inc. + +;; Maintainer: XEmacs Development Team +;; Keywords: help, internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: Not in FSF + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;;; Code: + +(defconst tutorial-supported-languages + '(("French" fr iso-8859-1) + ("German" de iso-8859-1) + ("Norwegian" no iso-8859-1) + ("Croatian" hr iso-8859-2)) + "Alist of supported languages in TUTORIAL files. +Add languages here, as more are translated.") + +;; TUTORIAL arg is XEmacs addition +(defun help-with-tutorial (&optional tutorial language) + "Select the XEmacs learn-by-doing tutorial. +Optional arg TUTORIAL specifies the tutorial file; default is \"TUTORIAL\". +With a prefix argument, choose the language." + (interactive "i\nP") + (or tutorial + (setq tutorial "TUTORIAL")) + (when (and language (consp language)) + (let ((completion-ignore-case t)) + (setq language (assoc (completing-read "Language: " + tutorial-supported-languages + nil t) + tutorial-supported-languages)))) + (when language + (setq tutorial (format "%s.%s" tutorial (cadr language)))) + (let ((file (expand-file-name tutorial "~"))) + (delete-other-windows) + (let ((buffer (or (get-file-buffer file) + (create-file-buffer file))) + (window-configuration (current-window-configuration))) + (condition-case error-data + (progn + (switch-to-buffer buffer) + (setq buffer-file-name file) + (setq default-directory (expand-file-name "~/")) + (setq buffer-auto-save-file-name nil) + ;; Because of non-Mule users, TUTORIALs are not coded + ;; independently, so we must guess the coding according to + ;; the language. + (let ((coding-system-for-read (nth 2 language))) + (insert-file-contents (expand-file-name tutorial + data-directory))) + (goto-char (point-min)) + ;; The 'didactic' blank lines: possibly insert blank lines + ;; around <> and replace << >> with [ ]. + (if (re-search-forward "^<<.+>>") + (let ((n (- (window-height (selected-window)) + (count-lines (point-min) (point-at-bol)) + 6))) + (if (< n 12) + (progn (beginning-of-line) (kill-line)) + ;; Some people get confused by the large gap + (delete-backward-char 2) + (insert "]") + (beginning-of-line) + (save-excursion + (delete-char 2) + (insert "[")) + (newline (/ n 2)) + (next-line 1) + (newline (- n (/ n 2)))))) + (goto-char (point-min)) + (set-buffer-modified-p nil)) + ;; TUTORIAL was not found: kill the buffer and restore the + ;; window configuration. + (file-error (kill-buffer buffer) + (set-window-configuration window-configuration) + ;; Now, signal the error + (signal (car error-data) (cdr error-data))))))) + + +(provide 'help-nomule) + +;;; help-nomule.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/help.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/help.el Mon Aug 13 10:04:58 2007 +0200 @@ -0,0 +1,1316 @@ +;;; help.el --- help commands for XEmacs. + +;; Copyright (C) 1985, 1986, 1992-4, 1997 Free Software Foundation, Inc. + +;; Maintainer: FSF +;; Keywords: help, internal, dumped + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs 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 XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Synched up with: FSF 19.30. + +;;; Commentary: + +;; This file is dumped with XEmacs. + +;; This code implements XEmacs's on-line help system, the one invoked by +;;`M-x help-for-help'. + +;; 06/11/1997 -- Converted to use char-after instead of broken +;; following-char. -slb + +;;; Code: + +;#### FSFmacs +;; Get the macro make-help-screen when this is compiled, +;; or run interpreted, but not when the compiled code is loaded. +;(eval-when-compile (require 'help-macro)) + +(defgroup help-appearance nil + "Appearance of help buffers" + :group 'help) + +(defvar help-map (let ((map (make-sparse-keymap))) + (set-keymap-name map 'help-map) + (set-keymap-prompt + map (purecopy (gettext "(Type ? for further options)"))) + map) + "Keymap for characters following the Help key.") + +;; global-map definitions moved to keydefs.el +(fset 'help-command help-map) + +(define-key help-map (vector help-char) 'help-for-help) +(define-key help-map "?" 'help-for-help) +(define-key help-map 'help 'help-for-help) + +(define-key help-map "\C-l" 'describe-copying) ; on \C-c in FSFmacs +(define-key help-map "\C-d" 'describe-distribution) +(define-key help-map "\C-w" 'describe-no-warranty) +(define-key help-map "a" 'hyper-apropos) ; 'command-apropos in FSFmacs +(define-key help-map "A" 'command-apropos) + +(define-key help-map "b" 'describe-bindings) +(define-key help-map "B" 'describe-beta) +(define-key help-map "\C-p" 'describe-pointer) + +(define-key help-map "C" 'customize) +(define-key help-map "c" 'describe-key-briefly) +(define-key help-map "k" 'describe-key) + +(define-key help-map "d" 'describe-function) +(define-key help-map "e" 'describe-last-error) +(define-key help-map "f" 'describe-function) + +(define-key help-map "F" 'xemacs-local-faq) + +;;; Setup so Hyperbole can be autoloaded from a key. +;;; Choose a key on which to place the Hyperbole menus. +;;; For most people this key binding will work and will be equivalent +;;; to {C-h h}. +;;; +(or (where-is-internal 'hyperbole) + (where-is-internal 'hui:menu) + (define-key help-map "h" 'hyperbole)) +(autoload 'hyperbole "hsite" "Hyperbole info manager menus." t) + +(define-key help-map "i" 'info) +(define-key help-map '(control i) 'Info-query) +;; FSFmacs has Info-goto-emacs-command-node on C-f, no binding +;; for Info-elisp-ref +(define-key help-map '(control c) 'Info-goto-emacs-command-node) +(define-key help-map '(control k) 'Info-goto-emacs-key-command-node) +(define-key help-map '(control f) 'Info-elisp-ref) + +(define-key help-map "l" 'view-lossage) + +(define-key help-map "m" 'describe-mode) + +(define-key help-map "\C-n" 'view-emacs-news) +(define-key help-map "n" 'view-emacs-news) + +(define-key help-map "p" 'finder-by-keyword) +(autoload 'finder-by-keyword "finder" + "Find packages matching a given keyword." t) + +(define-key help-map "s" 'describe-syntax) + +(define-key help-map "t" 'help-with-tutorial) + +(define-key help-map "w" 'where-is) + +(define-key help-map "v" 'describe-variable) + +(if (fboundp 'view-last-error) + (define-key help-map "e" 'view-last-error)) + + +(define-key help-map "q" 'help-quit) + +;#### This stuff was an attempt to have font locking and hyperlinks in the +;help buffer, but it doesn't really work. Some of this stuff comes from +;FSF Emacs; but the FSF Emacs implementation is rather broken, as usual. +;What needs to happen is this: +; +; -- we probably need a "hyperlink mode" from which help-mode is derived. +; -- this means we probably need multiple inheritance of modes! +; Thankfully this is not hard to implement; we already have the +; ability for a keymap to have multiple parents. However, we'd +; have to define any multiply-inherited-from modes using a standard +; `define-mode' construction instead of manually doing it, because +; we don't want each guy calling `kill-all-local-variables' and +; messing up the previous one. +; -- we need to scan the buffer ourselves (not from font-lock, because +; the user might not have font-lock enabled) and highlight only +; those words that are *documented* functions and variables (and +; probably excluding words without dashes in them unless enclosed +; in quotes, so that common words like "list" and "point" don't +; become hyperlinks. +; -- we should *not* use font-lock keywords like below. Instead we +; should add the font-lock stuff ourselves during the scanning phase, +; if font-lock is enabled in this buffer. + +;(defun help-follow-reference (event extent user-data) +; (let ((symbol (intern-soft (extent-string extent)))) +; (cond ((and symbol (fboundp symbol)) +; (describe-function symbol)) +; ((and symbol (boundp symbol)) +; (describe-variable symbol)) +; (t nil)))) + +;(defvar help-font-lock-keywords +; (let ((name-char "[-+a-zA-Z0-9_*]") (sym-char "[-+a-zA-Z0-9_:*]")) +; (list +; ;; +; ;; The symbol itself. +; (list (concat "\\`\\(" name-char "+\\)\\(:\\)?") +; '(1 (if (match-beginning 2) +; 'font-lock-function-name-face +; 'font-lock-variable-name-face) +; nil t)) +; ;; +; ;; Words inside `' which tend to be symbol names. +; (list (concat "`\\(" sym-char sym-char "+\\)'") +; 1 '(prog1 +; 'font-lock-reference-face +; (add-list-mode-item (match-beginning 1) +; (match-end 1) +; nil +; 'help-follow-reference)) +; t) +; ;; +; ;; CLisp `:' keywords as references. +; (list (concat "\\<:" sym-char "+\\>") 0 'font-lock-reference-face t))) +; "Default expressions to highlight in Help mode.") + +;(put 'help-mode 'font-lock-defaults '(help-font-lock-keywords)) + +(define-derived-mode help-mode view-major-mode "Help" + "Major mode for viewing help text. +Entry to this mode runs the normal hook `help-mode-hook'. +Commands: +\\{help-mode-map}" + ) + +(define-key help-mode-map "q" 'help-mode-quit) +(define-key help-mode-map "f" 'find-function-at-point) + +(defun describe-function-at-point () + "Describe directly the function at point in the other window." + (interactive) + (let ((symb (function-at-point))) + (when symb + (describe-function symb)))) +(defun describe-variable-at-point () + "Describe directly the variable at point in the other window." + (interactive) + (let ((symb (variable-at-point))) + (when symb + (describe-variable symb)))) +(defun help-next-symbol () + "Move point to the next quoted symbol." + (interactive) + (search-forward "`" nil t)) +(defun help-prev-symbol () + "Move point to the previous quoted symbol." + (interactive) + (search-backward "'" nil t)) +(define-key help-mode-map "d" 'describe-function-at-point) +(define-key help-mode-map "v" 'describe-variable-at-point) +(define-key help-mode-map [tab] 'help-next-symbol) +(define-key help-mode-map [(shift tab)] 'help-prev-symbol) + + +(defun help-mode-quit () + "Exits from help mode, possibly restoring the previous window configuration. +Bury the help buffer to the end of the buffer list." + (interactive) + (let ((buf (current-buffer))) + (cond ((frame-property (selected-frame) 'help-window-config) + (set-window-configuration + (frame-property (selected-frame) 'help-window-config)) + (set-frame-property (selected-frame) 'help-window-config nil)) + ((not (one-window-p)) + (delete-window))) + (bury-buffer buf))) + +(defun help-quit () + (interactive) + nil) + +;; This is a grody hack of the same genotype as `advertised-undo'; if the +;; bindings of Backspace and C-h are the same, we want the menubar to claim +;; that `info' in invoked with `C-h i', not `BS i'. + +(defun deprecated-help-command () + (interactive) + (if (eq 'help-command (key-binding "\C-h")) + (setq unread-command-event (character-to-event ?\C-h)) + (help-for-help))) + +;;(define-key global-map 'backspace 'deprecated-help-command) + +;; This function has been moved to help-nomule.el and mule-help.el. +;; TUTORIAL arg is XEmacs addition +;(defun help-with-tutorial (&optional tutorial) +; "Select the XEmacs learn-by-doing tutorial. +;Optional arg TUTORIAL specifies the tutorial file; default is \"TUTORIAL\"." +; (interactive) +; (if (null tutorial) +; (setq tutorial "TUTORIAL")) +; (let ((file (expand-file-name (concat "~/" tutorial)))) +; (delete-other-windows) +; (if (get-file-buffer file) +; (switch-to-buffer (get-file-buffer file)) +; (switch-to-buffer (create-file-buffer file)) +; (setq buffer-file-name file) +; (setq default-directory (expand-file-name "~/")) +; (setq buffer-auto-save-file-name nil) +; (insert-file-contents (expand-file-name tutorial data-directory)) +; (goto-char (point-min)) +; (search-forward "\n<<") +; (delete-region (point-at-bol) (point-at-eol)) +; (let ((n (- (window-height (selected-window)) +; (count-lines (point-min) (point)) +; 6))) +; (if (< n 12) +; (newline n) +; ;; Some people get confused by the large gap. +; (newline (/ n 2)) +; (insert "[Middle of page left blank for didactic purposes. " +; "Text continues below]") +; (newline (- n (/ n 2))))) +; (goto-char (point-min)) +; (set-buffer-modified-p nil)))) + +;; used by describe-key, describe-key-briefly, insert-key-binding, etc. + +(defun key-or-menu-binding (key &optional menu-flag) + "Return the command invoked by KEY. +Like `key-binding', but handles menu events and toolbar presses correctly. +KEY is any value returned by `next-command-event'. +MENU-FLAG is a symbol that should be set to T if KEY is a menu event, + or NIL otherwise" + (let (defn) + (and menu-flag (set menu-flag nil)) + ;; If the key typed was really a menu selection, grab the form out + ;; of the event object and intuit the function that would be called, + ;; and describe that instead. + (if (and (vectorp key) (= 1 (length key)) + (or (misc-user-event-p (aref key 0)) + (eq (car-safe (aref key 0)) 'menu-selection))) + (let ((event (aref key 0))) + (setq defn (if (eventp event) + (list (event-function event) (event-object event)) + (cdr event))) + (and menu-flag (set menu-flag t)) + (when (eq (car defn) 'eval) + (setq defn (car (cdr defn)))) + (when (eq (car-safe defn) 'call-interactively) + (setq defn (car (cdr defn)))) + (when (and (consp defn) (null (cdr defn))) + (setq defn (car defn)))) + ;; else + (setq defn (key-binding key))) + ;; kludge: if a toolbar button was pressed on, try to find the + ;; binding of the toolbar button. + (if (and (eq defn 'press-toolbar-button) + (vectorp key) + (button-press-event-p (aref key (1- (length key))))) + ;; wait for the button release. We're on shaky ground here ... + (let ((event (next-command-event)) + button) + (if (and (button-release-event-p event) + (event-over-toolbar-p event) + (eq 'release-and-activate-toolbar-button + (key-binding (vector event))) + (setq button (event-toolbar-button event))) + (toolbar-button-callback button) + ;; if anything went wrong, try returning the binding of + ;; the button-up event, of the original binding + (or (key-or-menu-binding (vector event)) + defn))) + ;; no toolbar kludge + defn) + )) + +(defun describe-key-briefly (key) + "Print the name of the function KEY invokes. KEY is a string." + (interactive "kDescribe key briefly: ") + (let (defn menup) + (setq defn (key-or-menu-binding key 'menup)) + (if (or (null defn) (integerp defn)) + (message "%s is undefined" (key-description key)) + ;; If it's a keyboard macro which trivially invokes another command, + ;; document that instead. + (if (or (stringp defn) (vectorp defn)) + (setq defn (or (key-binding defn) + defn))) + (let ((last-event (and (vectorp key) + (aref key (1- (length key)))))) + (message (if (or (button-press-event-p last-event) + (button-release-event-p last-event)) + (gettext "%s at that spot runs the command %s") + (gettext "%s runs the command %s")) + ;; This used to say 'This menu item' but it could also + ;; be a scrollbar event. We can't distinguish at the + ;; moment. + (if menup "This item" (key-description key)) + (if (symbolp defn) defn (prin1-to-string defn))))))) + +;; #### this is a horrible piece of shit function that should +;; not exist. In FSF 19.30 this function has gotten three times +;; as long and has tons and tons of dumb shit checking +;; special-display-buffer-names and such crap. I absolutely +;; refuse to insert that Ebolification here. I wanted to delete +;; this function entirely but Mly bitched. +;; +;; If your user-land code calls this function, rewrite it to +;; call with-displaying-help-buffer. + +(defun print-help-return-message (&optional function) + "Display or return message saying how to restore windows after help command. +Computes a message and applies the optional argument FUNCTION to it. +If FUNCTION is nil, applies `message' to it, thus printing it." + (and (not (get-buffer-window standard-output)) + (funcall + (or function 'message) + (concat + (substitute-command-keys + (if (one-window-p t) + (if pop-up-windows + (gettext "Type \\[delete-other-windows] to remove help window.") + (gettext "Type \\[switch-to-buffer] RET to remove help window.")) + (gettext "Type \\[switch-to-buffer-other-window] RET to restore the other window."))) + (substitute-command-keys + (gettext " \\[scroll-other-window] to scroll the help.")))))) + +(defcustom help-selects-help-window t + "*If nil, use the \"old Emacs\" behavior for Help buffers. +This just displays the buffer in another window, rather than selecting +the window." + :type 'boolean + :group 'help-appearance) + +;; Use this function for displaying help when C-h something is pressed +;; or in similar situations. Do *not* use it when you are displaying +;; a help message and then prompting for input in the minibuffer -- +;; this macro usually selects the help buffer, which is not what you +;; want in those situations. + +;;; ### Should really be a macro (as suggested above) to eliminate the +;;; requirement of caller to code a lambda form in THUNK -- mrb +(defun with-displaying-help-buffer (thunk) + (let ((winconfig (current-window-configuration)) + (was-one-window (one-window-p)) + (help-not-visible + (not (and (windows-of-buffer "*Help*") ;shortcut + (member (selected-frame) + (mapcar 'window-frame + (windows-of-buffer "*Help*"))))))) + (prog1 (with-output-to-temp-buffer "*Help*" + (prog1 (funcall thunk) + (save-excursion + (set-buffer standard-output) + (help-mode)))) + (let ((helpwin (get-buffer-window "*Help*"))) + (when helpwin + (with-current-buffer (window-buffer helpwin) + ;; If the *Help* buffer is already displayed on this + ;; frame, don't override the previous configuration + (when help-not-visible + (set-frame-property (selected-frame) + 'help-window-config winconfig))) + (when help-selects-help-window + (select-window helpwin)) + (cond ((eq helpwin (selected-window)) + (display-message 'command + (substitute-command-keys "Type \\[help-mode-quit] to remove help window, \\[scroll-up] to scroll the help."))) + (was-one-window + (display-message 'command + (substitute-command-keys "Type \\[delete-other-windows] to remove help window, \\[scroll-other-window] to scroll the help."))) + (t + (display-message 'command + (substitute-command-keys "Type \\[switch-to-buffer-other-window] to restore the other window, \\[scroll-other-window] to scroll the help."))))))))) + +(defun describe-key (key) + "Display documentation of the function invoked by KEY. +KEY is a string, or vector of events. +When called interactively, KEY may also be a menu selection." + (interactive "kDescribe key: ") + (let ((defn (key-or-menu-binding key))) + (if (or (null defn) (integerp defn)) + (message "%s is undefined" (key-description key)) + (with-displaying-help-buffer + (lambda () + (princ (key-description key)) + (princ " runs ") + (if (symbolp defn) (princ (format "`%S'" defn)) + (prin1 defn)) + (princ "\n\n") + (cond ((or (stringp defn) (vectorp defn)) + (let ((cmd (key-binding defn))) + (if (not cmd) + (princ "a keyboard macro") + (progn + (princ "a keyboard macro which runs the command ") + (prin1 cmd) + (princ ":\n\n") + (if (documentation cmd) (princ (documentation cmd))))))) + ((and (consp defn) (not (eq 'lambda (car-safe defn)))) + (let ((describe-function-show-arglist nil)) + (describe-function-1 (car defn) standard-output))) + ((symbolp defn) + (describe-function-1 defn standard-output)) + ((documentation defn) + (princ (documentation defn))) + (t + (princ "not documented")))))))) + +(defun describe-mode () + "Display documentation of current major mode and minor modes. +For this to work correctly for a minor mode, the mode's indicator variable +\(listed in `minor-mode-alist') must also be a function whose documentation +describes the minor mode." + (interactive) + (with-displaying-help-buffer + (lambda () + ;; XEmacs change: print the major-mode documentation before + ;; the minor modes. + (princ mode-name) + (princ " mode:\n") + (princ (documentation major-mode)) + (princ "\n\n----\n\n") + (let ((minor-modes minor-mode-alist)) + (while minor-modes + (let* ((minor-mode (car (car minor-modes))) + (indicator (car (cdr (car minor-modes))))) + ;; Document a minor mode if it is listed in minor-mode-alist, + ;; bound locally in this buffer, non-nil, and has a function + ;; definition. + (if (and (boundp minor-mode) + (symbol-value minor-mode) + (fboundp minor-mode)) + (let ((pretty-minor-mode minor-mode)) + (if (string-match "-mode\\'" (symbol-name minor-mode)) + (setq pretty-minor-mode + (capitalize + (substring (symbol-name minor-mode) + 0 (match-beginning 0))))) + (while (and (consp indicator) (extentp (car indicator))) + (setq indicator (cdr indicator))) + (while (and indicator (symbolp indicator)) + (setq indicator (symbol-value indicator))) + (princ (format "%s minor mode (indicator%s):\n" + pretty-minor-mode indicator)) + (princ (documentation minor-mode)) + (princ "\n\n----\n\n")))) + (setq minor-modes (cdr minor-modes))))))) + +;; So keyboard macro definitions are documented correctly +(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro)) + +(defun describe-distribution () + "Display info on how to obtain the latest version of XEmacs." + (interactive) + (find-file-read-only + (expand-file-name "DISTRIB" data-directory))) + +(defun describe-beta () + "Display info on how to deal with Beta versions of XEmacs." + (interactive) + (find-file-read-only + (expand-file-name "BETA" data-directory)) + (goto-char (point-min))) + +(defun describe-copying () + "Display info on how you may redistribute copies of XEmacs." + (interactive) + (find-file-read-only + (expand-file-name "COPYING" data-directory)) + (goto-char (point-min))) + +(defun describe-pointer () + "Show a list of all defined mouse buttons, and their definitions." + (interactive) + (describe-bindings nil t)) + +(defun describe-project () + "Display info on the GNU project." + (interactive) + (find-file-read-only + (expand-file-name "GNU" data-directory)) + (goto-char (point-min))) + +(defun describe-no-warranty () + "Display info on all the kinds of warranty XEmacs does NOT have." + (interactive) + (describe-copying) + (let (case-fold-search) + (search-forward "NO WARRANTY") + (recenter 0))) + +(defun describe-bindings (&optional prefix mouse-only-p) + "Show a list of all defined keys, and their definitions. +The list is put in a buffer, which is displayed. +If the optional argument PREFIX is supplied, only commands which +start with that sequence of keys are described. +If the second argument (prefix arg, interactively) is non-null +then only the mouse bindings are displayed." + (interactive (list nil current-prefix-arg)) + (with-displaying-help-buffer + (lambda () + (describe-bindings-1 prefix mouse-only-p)))) + +(defun describe-bindings-1 (&optional prefix mouse-only-p) + (let ((heading (if mouse-only-p + (gettext "button binding\n------ -------\n") + (gettext "key binding\n--- -------\n"))) + (buffer (current-buffer)) + (minor minor-mode-map-alist) + (local (current-local-map)) + (shadow '())) + (set-buffer standard-output) + (while minor + (let ((sym (car (car minor))) + (map (cdr (car minor)))) + (if (symbol-value-in-buffer sym buffer nil) + (progn + (insert (format "Minor Mode Bindings for `%s':\n" + sym) + heading) + (describe-bindings-internal map nil shadow prefix mouse-only-p) + (insert "\n") + (setq shadow (cons map shadow)))) + (setq minor (cdr minor)))) + (if local + (progn + (insert "Local Bindings:\n" heading) + (describe-bindings-internal local nil shadow prefix mouse-only-p) + (insert "\n") + (setq shadow (cons local shadow)))) + (insert "Global Bindings:\n" heading) + (describe-bindings-internal (current-global-map) + nil shadow prefix mouse-only-p) + (when (and prefix function-key-map (not mouse-only-p)) + (insert "\nFunction key map translations:\n" heading) + (describe-bindings-internal function-key-map nil nil prefix mouse-only-p)) + (set-buffer buffer))) + +(defun describe-prefix-bindings () + "Describe the bindings of the prefix used to reach this command. +The prefix described consists of all but the last event +of the key sequence that ran this command." + (interactive) + (let* ((key (this-command-keys)) + (prefix (make-vector (1- (length key)) nil)) + i) + (setq i 0) + (while (< i (length prefix)) + (aset prefix i (aref key i)) + (setq i (1+ i))) + (with-displaying-help-buffer + (lambda () + (princ "Key bindings starting with ") + (princ (key-description prefix)) + (princ ":\n\n") + (describe-bindings-1 prefix nil))))) + +;; Make C-h after a prefix, when not specifically bound, +;; run describe-prefix-bindings. +(setq prefix-help-command 'describe-prefix-bindings) + +(defun view-emacs-news () + "Display info on recent changes to XEmacs." + (interactive) + #-infodock (require 'outl-mouse) + (find-file (expand-file-name "NEWS" data-directory))) + +(defun xemacs-www-page () + "Go to the XEmacs World Wide Web page." + (interactive) + (funcall browse-url-browser-function "http://www.xemacs.org/")) + +(defun xemacs-www-faq () + "View the latest and greatest XEmacs FAQ using the World Wide Web." + (interactive) + (funcall browse-url-browser-function "http://www.xemacs.org/faq/index.html")) + +(defun xemacs-local-faq () + "View the local copy of the XEmacs FAQ. +If you have access to the World Wide Web, you should use `xemacs-www-faq' +instead, to ensure that you get the most up-to-date information." + (interactive) + (save-window-excursion + (info) + (Info-find-node "xemacs-faq" "Top")) + (switch-to-buffer "*info*")) + +(defcustom view-lossage-key-count 100 + "*Number of keys `view-lossage' shows. +The maximum number of available keys is governed by `recent-keys-ring-size'." + :type 'integer + :group 'help) + +(defcustom view-lossage-message-count 100 + "*Number of minibuffer messages `view-lossage' shows." + :type 'integer + :group 'help) + +(defun view-lossage () + "Display recent input keystrokes and recent minibuffer messages. +The number of keys shown is controlled by `view-lossage-key-count'. +The number of messages shown is controlled by `view-lossage-message-count'." + (interactive) + (with-displaying-help-buffer + (lambda () + (princ (key-description (recent-keys view-lossage-key-count))) + (save-excursion + (set-buffer standard-output) + (goto-char (point-min)) + (insert "Recent keystrokes:\n\n") + (while (progn (move-to-column 50) (not (eobp))) + (search-forward " " nil t) + (insert "\n"))) + ;; XEmacs addition + (princ "\n\n\nRecent minibuffer messages (most recent first):\n\n") + (save-excursion + (let ((buffer (get-buffer " *Message-Log*")) + (count 0) + oldpoint) + (set-buffer buffer) + (goto-char (point-max)) + (set-buffer standard-output) + (while (and (> (point buffer) (point-min buffer)) + (< count view-lossage-message-count)) + (setq oldpoint (point buffer)) + (forward-line -1 buffer) + (insert-buffer-substring buffer (point buffer) oldpoint) + (setq count (1+ count)))))))) + +(define-function 'help 'help-for-help) +;; #### FSF calls `make-help-screen' here. We need to port `help-macro.el'. +(defun help-for-help () + "You have typed \\[help-for-help], the help character. Type a Help option: +\(Use SPC or DEL to scroll through this text. Type \\\\[help-quit] to exit the Help command.) + +\\[hyper-apropos] Type a substring; it shows a hypertext list of + functions and variables that contain that substring. + See also the `apropos' command. +\\[command-apropos] Type a substring; it shows a list of commands + (interactively callable functions) that contain that substring. +\\[describe-bindings] Table of all key bindings. +\\[describe-key-briefly] Type a command key sequence; + it displays the function name that sequence runs. +\\[Info-goto-emacs-command-node] Type a function name; it displays the Info node for that command. +\\[describe-function] Type a function name; it shows its documentation. +\\[Info-elisp-ref] Type a function name; it jumps to the full documentation + in the XEmacs Lisp Programmer's Manual. +\\[xemacs-local-faq] Local copy of the XEmacs FAQ. +\\[info] Info documentation reader. +\\[Info-query] Type an Info file name; it displays it in Info reader. +\\[describe-key] Type a command key sequence; + it displays the documentation for the command bound to that key. +\\[Info-goto-emacs-key-command-node] Type a command key sequence; + it displays the Info node for the command bound to that key. +\\[view-lossage] Recent input keystrokes and minibuffer messages. +\\[describe-mode] Documentation of current major and minor modes. +\\[view-emacs-news] News of recent XEmacs changes. +\\[finder-by-keyword] Type a topic keyword; it finds matching packages. +\\[describe-pointer] Table of all mouse-button bindings. +\\[describe-syntax] Contents of syntax table with explanations. +\\[help-with-tutorial] XEmacs learn-by-doing tutorial. +\\[describe-variable] Type a variable name; it displays its documentation and value. +\\[where-is] Type a command name; it displays which keystrokes invoke that command. +\\[describe-distribution] XEmacs ordering information. +\\[describe-no-warranty] Information on absence of warranty for XEmacs. +\\[describe-copying] XEmacs copying permission (General Public License)." + (interactive) + (let ((help-key (copy-event last-command-event)) + event char) + (message (gettext "A B C F I K L M N P S T V W C-c C-d C-n C-w. Type %s again for more help: ") + ;; arrgh, no room for "C-i C-k C-f" !! + (single-key-description help-key)) + (setq event (next-command-event) + char (event-to-character event)) + (if (or (equal event help-key) + (eq char ??) + (eq 'help-command (key-binding event))) + (save-window-excursion + (switch-to-buffer "*Help*") + ;; #### I18N3 should mark buffer as output-translating + (delete-other-windows) + (let ((buffer-read-only nil)) + (erase-buffer) + (insert (documentation 'help-for-help))) + (goto-char (point-min)) + (while (or (equal event help-key) + (eq char ??) + (eq 'help-command (key-binding event)) + (eq char ?\ ) + (eq 'scroll-up (key-binding event)) + (eq char ?\177) + (and (not (eq char ?b)) + (eq 'scroll-down (key-binding event)))) + (if (or (eq char ?\ ) + (eq 'scroll-up (key-binding event))) + (scroll-up)) + (if (or (eq char ?\177) + (and (not (eq char ?b)) + (eq 'scroll-down (key-binding event)))) + (scroll-down)) + ;; write this way for I18N3 snarfing + (if (pos-visible-in-window-p (point-max)) + (message "A B C F I K L M N P S T V W C-c C-d C-n C-w C-i C-k C-f: ") + (message "A B C F I K L M N P S T V W C-c C-d C-n C-w C-i C-k C-f or Space to scroll: ")) + (let ((cursor-in-echo-area t)) + (setq event (next-command-event event) + char (or (event-to-character event) event)))))) + (let ((defn (or (lookup-key help-map (vector event)) + (and (numberp char) + (lookup-key help-map (make-string 1 (downcase char))))))) + (message nil) + (if defn + (call-interactively defn) + (ding))))) + +(defun function-called-at-point () + "Return the function which is called by the list containing point. +If that gives no function, return the function whose name is around point. +If that doesn't give a function, return nil." + (or (condition-case () + (save-excursion + (save-restriction + (narrow-to-region (max (point-min) (- (point) 1000)) (point-max)) + (backward-up-list 1) + (forward-char 1) + (let (obj) + (setq obj (read (current-buffer))) + (and (symbolp obj) (fboundp obj) obj)))) + (error nil)) + (condition-case () + (let ((stab (syntax-table))) + (unwind-protect + (save-excursion + (set-syntax-table emacs-lisp-mode-syntax-table) + (or (not (zerop (skip-syntax-backward "_w"))) + (eq (char-syntax (char-after (point))) ?w) + (eq (char-syntax (char-after (point))) ?_) + (forward-sexp -1)) + (skip-chars-forward "`'") + (let ((obj (read (current-buffer)))) + (and (symbolp obj) (fboundp obj) obj))) + (set-syntax-table stab))) + (error nil)))) + +(defun function-at-point () + "Return the function whose name is around point. +If that gives no function, return the function which is called by the +list containing point. If that doesn't give a function, return nil." + (or (condition-case () + (let ((stab (syntax-table))) + (unwind-protect + (save-excursion + (set-syntax-table emacs-lisp-mode-syntax-table) + (or (not (zerop (skip-syntax-backward "_w"))) + (eq (char-syntax (char-after (point))) ?w) + (eq (char-syntax (char-after (point))) ?_) + (forward-sexp -1)) + (skip-chars-forward "`'") + (let ((obj (read (current-buffer)))) + (and (symbolp obj) (fboundp obj) obj))) + (set-syntax-table stab))) + (error nil)) + (condition-case () + (save-excursion + (save-restriction + (narrow-to-region (max (point-min) (- (point) 1000)) + (point-max)) + (backward-up-list 1) + (forward-char 1) + (let (obj) + (setq obj (read (current-buffer))) + (and (symbolp obj) (fboundp obj) obj)))) + (error nil)))) + +;; Default to nil for the non-hackers? Not until we find a way to +;; distinguish hackers from non-hackers automatically! +(defcustom describe-function-show-arglist t + "*If non-nil, describe-function will show its arglist, +unless the function is autoloaded." + :type 'boolean + :group 'help-appearance) + +(defun describe-function-find-file (function) + (let ((files load-history) + file) + (while files + (if (memq function (cdr (car files))) + (setq file (car (car files)) + files nil)) + (setq files (cdr files))) + file)) + +(defun describe-function (function) + "Display the full documentation of FUNCTION (a symbol). +When run interactively, it defaults to any function found by +`function-at-point'." + (interactive + (let* ((fn (function-at-point)) + (val (let ((enable-recursive-minibuffers t)) + (completing-read + (if fn + (format (gettext "Describe function (default %s): ") + fn) + (gettext "Describe function: ")) + obarray 'fboundp t nil 'function-history)))) + (list (if (equal val "") fn (intern val))))) + (with-displaying-help-buffer + (lambda () + (describe-function-1 function standard-output) + ;; Return the text we displayed. + (buffer-string nil nil standard-output)))) + +(defun function-obsolete-p (function) + "Return non-nil if FUNCTION is obsolete." + (not (null (get function 'byte-obsolete-info)))) + +(defun function-obsoleteness-doc (function) + "If FUNCTION is obsolete, return a string describing this." + (let ((obsolete (get function 'byte-obsolete-info))) + (if obsolete + (format "Obsolete; %s" + (if (stringp (car obsolete)) + (car obsolete) + (format "use `%s' instead." (car obsolete))))))) + +(defun function-compatible-p (function) + "Return non-nil if FUNCTION is present for Emacs compatibility." + (not (null (get function 'byte-compatible-info)))) + +(defun function-compatibility-doc (function) + "If FUNCTION is Emacs compatible, return a string describing this." + (let ((compatible (get function 'byte-compatible-info))) + (if compatible + (format "Emacs Compatible; %s" + (if (stringp (car compatible)) + (car compatible) + (format "use `%s' instead." (car compatible))))))) + +;Here are all the possibilities below spelled out, for the benefit +;of the I18N3 snarfer. +; +;(gettext "a built-in function") +;(gettext "an interactive built-in function") +;(gettext "a built-in macro") +;(gettext "an interactive built-in macro") +;(gettext "a compiled Lisp function") +;(gettext "an interactive compiled Lisp function") +;(gettext "a compiled Lisp macro") +;(gettext "an interactive compiled Lisp macro") +;(gettext "a Lisp function") +;(gettext "an interactive Lisp function") +;(gettext "a Lisp macro") +;(gettext "an interactive Lisp macro") +;(gettext "a mocklisp function") +;(gettext "an interactive mocklisp function") +;(gettext "a mocklisp macro") +;(gettext "an interactive mocklisp macro") +;(gettext "an autoloaded Lisp function") +;(gettext "an interactive autoloaded Lisp function") +;(gettext "an autoloaded Lisp macro") +;(gettext "an interactive autoloaded Lisp macro") + +(defun describe-function-1 (function stream &optional nodoc) + (princ (format "`%S' is " function) stream) + (let* ((def function) + (doc (condition-case nil + (or (documentation function) + (gettext "not documented")) + (void-function ""))) + aliases file-name autoload-file kbd-macro-p fndef macrop) + (while (and (symbolp def) (fboundp def)) + (when (not (eq def function)) + (setq aliases + (if aliases + ;; I18N3 Need gettext due to concat + (concat aliases + (format + "\n which is an alias for `%s', " + (symbol-name def))) + (format "an alias for `%s', " (symbol-name def))))) + (setq def (symbol-function def))) + (if (compiled-function-p def) + (setq file-name (compiled-function-annotation def))) + (if (eq 'macro (car-safe def)) + (setq fndef (cdr def) + file-name (and (compiled-function-p (cdr def)) + (compiled-function-annotation (cdr def))) + macrop t) + (setq fndef def)) + (if aliases (princ aliases stream)) + (let ((int #'(lambda (string an-p macro-p) + (princ (format + (gettext (concat + (cond ((commandp def) + "an interactive ") + (an-p "an ") + (t "a ")) + "%s" + (if macro-p " macro" " function"))) + string) + stream)))) + (cond ((or (stringp def) (vectorp def)) + (princ "a keyboard macro." stream) + (setq kbd-macro-p t)) + ((subrp fndef) + (funcall int "built-in" nil macrop)) + ((compiled-function-p fndef) + (funcall int "compiled Lisp" nil macrop)) +; XEmacs -- we handle aliases above. +; ((symbolp fndef) +; (princ (format "alias for `%s'" +; (prin1-to-string def)) stream)) + ((eq (car-safe fndef) 'lambda) + (funcall int "Lisp" nil macrop)) + ((eq (car-safe fndef) 'mocklisp) + (funcall int "mocklisp" nil macrop)) + ((eq (car-safe def) 'autoload) + (setq autoload-file (elt def 1)) + (funcall int "autoloaded Lisp" t (elt def 4))) + ((and (symbolp def) (not (fboundp def))) + (princ "a symbol with a void (unbound) function definition." stream)) + (t + nil))) + (princ "\n") + (if autoload-file + (princ (format " -- autoloads from \"%s\"\n" autoload-file) stream)) + (or file-name + (setq file-name (describe-function-find-file function))) + (if file-name + (princ (format " -- loaded from \"%s\"\n" file-name)) stream) +;; (terpri stream) + (if describe-function-show-arglist + (let ((arglist + (cond ((compiled-function-p fndef) + (compiled-function-arglist fndef)) + ((eq (car-safe fndef) 'lambda) + (nth 1 fndef)) + ((and (subrp fndef) + (string-match + "[\n\t ]*\narguments: ?(\\(.*\\))\n?\\'" + doc)) + (prog1 + (substring doc (match-beginning 1) (match-end 1)) + (setq doc (substring doc 0 (match-beginning 0))))) + (t t)))) + (if (listp arglist) + (progn +;; (princ " ") + (princ (cons function + (mapcar (lambda (arg) + (if (memq arg '(&optional &rest)) + arg + (intern (upcase (symbol-name arg))))) + arglist)) stream) + (terpri stream))) + (if (stringp arglist) + (princ (format "(%s %s)\n" function arglist) stream)))) + (terpri stream) + (cond (kbd-macro-p + (princ "These characters are executed:\n\n\t" stream) + (princ (key-description def) stream) + (cond ((setq def (key-binding def)) + (princ (format "\n\nwhich executes the command %S.\n\n" def) stream) + (describe-function-1 def stream)))) + (nodoc nil) + (t + ;; tell the user about obsoleteness. + ;; If the function is obsolete and is aliased, don't + ;; even bother to report the documentation, as a further + ;; encouragement to use the new function. + (let ((obsolete (function-obsoleteness-doc function)) + (compatible (function-compatibility-doc function))) + (when obsolete + (princ obsolete stream) + (terpri stream) + (terpri stream)) + (when compatible + (princ compatible stream) + (terpri stream) + (terpri stream)) + (unless (and obsolete aliases) + (princ doc stream) + (unless (or (equal doc "") + (eq ?\n (aref doc (1- (length doc))))) + (terpri stream)))))))) + + +;;; ## this doesn't seem to be used for anything +;; (defun describe-function-arglist (function) +;; (interactive (list (or (function-at-point) +;; (error "no function call at point")))) +;; (let ((b nil)) +;; (unwind-protect +;; (save-excursion +;; (set-buffer (setq b (get-buffer-create " *arglist*"))) +;; (buffer-disable-undo b) +;; (erase-buffer) +;; (describe-function-1 function b t) +;; (goto-char (point-min)) +;; (end-of-line) +;; (or (eobp) (delete-char 1)) +;; (just-one-space) +;; (end-of-line) +;; (message (buffer-substring (point-min) (point)))) +;; (and b (kill-buffer b))))) + + +(defun variable-at-point () + (ignore-errors + (let ((stab (syntax-table))) + (unwind-protect + (save-excursion + (set-syntax-table emacs-lisp-mode-syntax-table) + (or (not (zerop (skip-syntax-backward "_w"))) + (eq (char-syntax (char-after (point))) ?w) + (eq (char-syntax (char-after (point))) ?_) + (forward-sexp -1)) + (skip-chars-forward "'") + (let ((obj (read (current-buffer)))) + (and (symbolp obj) (boundp obj) obj))) + (set-syntax-table stab))))) + +(defun variable-obsolete-p (variable) + "Return non-nil if VARIABLE is obsolete." + (not (null (get variable 'byte-obsolete-variable)))) + +(defun variable-obsoleteness-doc (variable) + "If VARIABLE is obsolete, return a string describing this." + (let ((obsolete (get variable 'byte-obsolete-variable))) + (if obsolete + (format "Obsolete; %s" + (if (stringp obsolete) + obsolete + (format "use `%s' instead." obsolete)))))) + +(defun variable-compatible-p (variable) + "Return non-nil if VARIABLE is Emacs compatible." + (not (null (get variable 'byte-compatible-variable)))) + +(defun variable-compatibility-doc (variable) + "If VARIABLE is Emacs compatible, return a string describing this." + (let ((compatible (get variable 'byte-compatible-variable))) + (if compatible + (format "Emacs Compatible; %s" + (if (stringp compatible) + compatible + (format "use `%s' instead." compatible)))))) + +(defun built-in-variable-doc (variable) + "Return a string describing whether VARIABLE is built-in." + (let ((type (built-in-variable-type variable))) + (case type + (integer "a built-in integer variable") + (const-integer "a built-in constant integer variable") + (boolean "a built-in boolean variable") + (const-boolean "a built-in constant boolean variable") + (object "a simple built-in variable") + (const-object "a simple built-in constant variable") + (const-specifier "a built-in constant specifier variable") + (current-buffer "a built-in buffer-local variable") + (const-current-buffer "a built-in constant buffer-local variable") + (default-buffer "a built-in default buffer-local variable") + (selected-console "a built-in console-local variable") + (const-selected-console "a built-in constant console-local variable") + (default-console "a built-in default console-local variable") + (t + (if type "an unknown type of built-in variable?" + "a variable declared in Lisp"))))) + +(defun describe-variable (variable) + "Display the full documentation of VARIABLE (a symbol)." + (interactive + (let* ((v (variable-at-point)) + (val (let ((enable-recursive-minibuffers t)) + (completing-read + (if v + (format "Describe variable (default %s): " v) + (gettext "Describe variable: ")) + obarray 'boundp t nil 'variable-history)))) + (list (if (equal val "") v (intern val))))) + (with-displaying-help-buffer + (lambda () + (let ((origvar variable) + aliases) + (let ((print-escape-newlines t)) + (princ (format "`%s' is " (symbol-name variable))) + (while (variable-alias variable) + (let ((newvar (variable-alias variable))) + (if aliases + ;; I18N3 Need gettext due to concat + (setq aliases + (concat aliases + (format "\n which is an alias for `%s'," + (symbol-name newvar)))) + (setq aliases + (format "an alias for `%s'," + (symbol-name newvar)))) + (setq variable newvar))) + (if aliases + (princ (format "%s" aliases))) + (princ (built-in-variable-doc variable)) + (princ ".\n\n") + (princ "Value: ") + (if (not (boundp variable)) + (princ "void") + (prin1 (symbol-value variable))) + (terpri) + (cond ((local-variable-p variable (current-buffer)) + (let* ((void (cons nil nil)) + (def (condition-case nil + (default-value variable) + (error void)))) + (princ "This value is specific to the current buffer.") + (terpri) + (if (local-variable-p variable nil) + (progn + (princ "(Its value is local to each buffer.)") + (terpri))) + (if (if (eq def void) + (boundp variable) + (not (eq (symbol-value variable) def))) + ;; #### I18N3 doesn't localize properly! + (progn (princ "Its default-value is ") + (if (eq def void) + (princ "void.") + (prin1 def)) + (terpri))))) + ((local-variable-p variable (current-buffer) t) + (princ "Setting it would make its value buffer-local.\n")))) + (terpri) + (princ "Documentation:") + (terpri) + (let ((doc (documentation-property variable 'variable-documentation)) + (obsolete (variable-obsoleteness-doc origvar)) + (compatible (variable-compatibility-doc origvar))) + (when obsolete + (princ obsolete) + (terpri) + (terpri)) + (when compatible + (princ compatible) + (terpri) + (terpri)) + ;; don't bother to print anything if variable is obsolete and aliased. + (when (or (not obsolete) (not aliases)) + (if doc + ;; note: documentation-property calls substitute-command-keys. + (princ doc) + (princ "not documented as a variable.")) + (terpri))) + ;; Return the text we displayed. + (buffer-string nil nil standard-output))))) + +(defun sorted-key-descriptions (keys &optional separator) + "Sort and separate the key descriptions for KEYS. +The sorting is done by length (shortest bindings first), and the bindings +are separated with SEPARATOR (\", \" by default)." + (mapconcat 'key-description + (sort keys #'(lambda (x y) + (< (length x) (length y)))) + (or separator ", "))) + +(defun where-is (definition) + "Print message listing key sequences that invoke specified command. +Argument is a command definition, usually a symbol with a function definition. +When run interactively, it defaults to any function found by +`function-at-point'." + (interactive + (let ((fn (function-at-point)) + (enable-recursive-minibuffers t) + val) + (setq val (read-command + (if fn (format "Where is command (default %s): " fn) + "Where is command: "))) + (list (if (equal (symbol-name val) "") + fn val)))) + (let ((keys (where-is-internal definition))) + (if keys + (message "%s is on %s" definition (sorted-key-descriptions keys)) + (message "%s is not on any keys" definition))) + nil) + +;; `locate-library' moved to "packages.el" + + +;; Functions ported from C into Lisp in XEmacs + +(defun describe-syntax () + "Describe the syntax specifications in the syntax table. +The descriptions are inserted in a buffer, which is then displayed." + (interactive) + (with-displaying-help-buffer + (lambda () + ;; defined in syntax.el + (describe-syntax-table (syntax-table) standard-output)))) + +(defun list-processes () + "Display a list of all processes. +\(Any processes listed as Exited or Signaled are actually eliminated +after the listing is made.)" + (interactive) + (with-output-to-temp-buffer "*Process List*" + (set-buffer standard-output) + (buffer-disable-undo standard-output) + (make-local-variable 'truncate-lines) + (setq truncate-lines t) + (let ((stream standard-output)) + ;; 00000000001111111111222222222233333333334444444444 + ;; 01234567890123456789012345678901234567890123456789 + ;; rewritten for I18N3. This one should stay rewritten + ;; so that the dashes will line up properly. + (princ "Proc Status Buffer Tty Command\n---- ------ ------ --- -------\n" stream) + (let ((tail (process-list))) + (while tail + (let* ((p (car tail)) + (pid (process-id p)) + (s (process-status p))) + (setq tail (cdr tail)) + (princ (format "%-13s" (process-name p)) stream) + ;(if (and (eq system-type 'vax-vms) + ; (eq s 'signal) + ; (< (process-exit-status p) NSIG)) + ; (princ (aref sys_errlist (process-exit-status p)) stream)) + (princ s stream) + (if (and (eq s 'exit) (/= (process-exit-status p) 0)) + (princ (format " %d" (process-exit-status p)) stream)) + (if (memq s '(signal exit closed)) + ;; Do delete-exited-processes' work + (delete-process p)) + (indent-to 22 1) ;#### + (let ((b (process-buffer p))) + (cond ((not b) + (princ "(none)" stream)) + ((not (buffer-name b)) + (princ "(killed)" stream)) + (t + (princ (buffer-name b) stream)))) + (indent-to 37 1) ;#### + (let ((tn (process-tty-name p))) + (cond ((not tn) + (princ "(none)" stream)) + (t + (princ (format "%s" tn) stream)))) + (indent-to 49 1) ;#### + (if (not (integerp pid)) + (progn + (princ "network stream connection " stream) + (princ (car pid) stream) + (princ "@" stream) + (princ (cdr pid) stream)) + (let ((cmd (process-command p))) + (while cmd + (princ (car cmd) stream) + (setq cmd (cdr cmd)) + (if cmd (princ " " stream))))) + (terpri stream))))))) + +;; `find-function' et al moved to "find-func.el" + +;;; help.el ends here diff -r f427b8ec4379 -r 41ff10fd062f lisp/hyperbole/ChangeLog --- a/lisp/hyperbole/ChangeLog Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,694 +0,0 @@ -1997-09-17 SL Baur - - * Makefile (autoloads): Fixup dependency. - -1997-07-08 Steven L Baur - - * hact.el (action:commandp): Don't reference bytecode objects as - vectors. - (action:params): Ditto. - -1997-07-07 Steven L Baur - - * hypb.el (hypb:function-copy): Don't reference bytecode objects - as vectors. - (hypb:function-symbol-replace): Document as broken. The - substition cannot be done without some thinking I'm not in the - mood for. - -1997-07-03 Steven L Baur - - * Makefile: Add autoloads dependencies. - -1997-06-27 Steven L Baur - - * wrolo-menu.el (TopLevel): Fix tests so that W3's id-menubar - simulation doesn't bollux up feature tests. - -Thu Mar 13 22:01:52 1997 Bob Weiner - -* wrolo.el (rolo-toggle-datestamps): Added. -* hui-mini.el (hui:menus): Added Cust/Toggle-Rolodex-Dates entry. -* hui-menu.el (hui-menu-options): Added Customization/Toggle-Rolodex-Dates - item. -* wrolo.el (rolo-add): Added wrolo-add-hook, executed after the record - is added. - (rolo-edit): Added wrolo-edit-hook, executed after point is - successfully moved to the record to edit. These can be used, for - example, to add and update date entries in address records. - (rolo-current-date): Added. - (rolo-set-date): Added and used as default wrolo-add-hook and - wrolo-edit-hook settings. - -Mon Mar 10 12:17:15 1997 Bob Weiner - -* hsys-w3.el (www-url): Eliminated call of external Web browser if not - running under a window system. - -Sun Mar 9 01:32:03 1997 Bob Weiner - -* hpath.el (hpath:url-at-p): - (hpath:www-at-p): Fixed bug that referred to an optional match - component without checking if it was matched. - (hpath:url-p): Changed doc to reflect that pathname can be optional. - -* hsite-ex.el: Added (require 'hyperbole) to ensure that this file - is loaded if hsite.el is autoloaded, e.g. under XEmacs. - -Thu Mar 6 14:14:05 1997 Bob Weiner - -* hui-mini.el (hyperbole): Added autoload special comment. - -Wed Mar 5 01:14:47 1997 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:center-line): -* kotl/kview.el (kcell-view:line): Changed calls to - kotl-mode:beginning-of-line to kotl-mode:start-of-line to avoid an - XEmacs byte compiler bug in some versions. The bug shows up when - kotl-mode:center-line is called on the first line of a cell and the - cell label is centered along with the line (the label should not - move). - -Tue Mar 4 20:45:52 1997 Bob Weiner - -* hsite-ex.el (hpath:find-alist): Modified to use `xv' to display xpm - files; it is more robust than `sxpm' in the face of limited colors. - -Mon Mar 3 12:06:49 1997 Bob Weiner - -* hui-menu.el (infodock-hyperbole-menu): Added :config 'Hyperbole - configurator to the menu so users can hide the Hyperbole - menu from the menubar if they don't use it, via menubar-configuration, - under XEmacs and InfoDock. - -Sun Mar 2 22:35:26 1997 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:set-cell-attribute): Changed - read-expression to read-minibuffer since GNU Emacs doesn't - have the former. - -Fri Feb 28 23:31:57 1997 Bob Weiner - -* kotl/kprop-xe.el (kproperty:put): Fixed problem with internal handling - of text property protocols within newer versions of XEmacs. The - `text-prop' symbol can no longer be set to `t'. It must be set to - a symbol from the property list of the extent that carries - text-properties. - -============================================================================== -V4.023 changes ^^^^: -============================================================================== - -Sat Feb 22 14:30:14 1997 Bob Weiner - -* hypb.el (hypb:ida-logo-keymap): Added conditional for Emacs keybinding. - -============================================================================== -V4.022 changes ^^^^: -============================================================================== - -Fri Feb 21 17:49:01 1997 Bob Weiner - -* hmouse-reg.el (hmouse-get-bindings): - (hmouse-setup): -* hmouse-sh.el (hmouse-get-bindings): - (hmouse-setup): -* hmouse-key.el (hmouse-set-bindings): -Modified to do nothing when running in batch mode (noninteractively). - - -============================================================================== -V4.021 changes ^^^^: -============================================================================== - -Tue Feb 18 18:57:27 1997 Bob Weiner - -* hui-mini.el (hui:menus): Added "Doc/About" menu item -* hui-menu.el (infodock-hyperbole-menu): Added "About" menu item. -* hypb.el (hypb:ida-logo-keymap): - (hypb:ida-home-page): - (hypb:display-file-with-logo): Added to support About Hyperbole command. - -Mon Feb 17 15:27:21 1997 Bob Weiner - -* hversion.el (hyperb:microcruft-os-p): Added. - -Sat Feb 15 16:03:42 1997 Bob Weiner - -* hpath.el (hpath:find): Fixed bug that returned nil (now is 't) if file - was displayed using a specialized function. - (hpath:find-line): Added to handle displaying of all files at - specific lines (hpath:find does not work for this use since it - may call external display functions). -* hactypes.el (link-to-file-line): Rewrote to call hpath:find-line. - -Fri Feb 14 11:39:09 1997 Bob Weiner - -* hrmail.el (rmail-forward): Updated to V19 compatibility. - -Sun Jan 26 14:32:28 1997 Bob Weiner - -* hmouse-sh.el (hmouse-get-bindings): -* hmouse-reg.el (hmouse-get-bindings): Rearranged order of initial - conditional so that lemacs or emacs19 always takes precedence over - hyperb:window-system setting, which may be "xterm". - -* hmouse-key.el (or hyperb:xemacs-p hyperb:emacs19-p): Prevent any attempt - to load pre-dumped mouse libraries when running under X terms on these - versions of emacs. - -* hyperbole.el (hbut:key-src): Added this autoload to avert error if the - rolodex is loaded before the Hyperbole system and then a rolo-edit, {e}, - request is made within the match buffer. - -* hgnus.el: Updated to support new Gnus gnus-msg.el replacement for gnuspost.el. - -* hversion.el (sm-window-sys-term): -* hbmap.el (hbmap:dir-user): Patched to support GNU Emacs running - natively under Windows NT. - -Tue Jan 14 15:45:14 1997 Bob Weiner - -* ../../etc/hypb-mouse.txt (Special Modes): Added Objective-C, Java and - Fortran support documentation. - -Mon Jan 6 18:59:13 1997 Bob Weiner - -* kotl/klink.el (klink:at-p): Eliminated matches to URLs for now. - -Wed Dec 25 22:01:05 1996 Bob Weiner - -* hmouse-tag.el: Changed all opening quotes in comments from ' to `. - -Tue Dec 10 16:40:09 1996 Bob Weiner - -* wrolo.el (wrolo-mode-syntax-table): Added to support syntactic selection - of delimited e-mail addresses. - -Fri Dec 6 12:34:31 1996 Bob Weiner - -* hmail.el (hmail:region): Fixed bug that extracted region from the wrong - buffer. - -Thu Dec 5 15:34:55 1996 Bob Weiner - -* hibtypes.el (annot-bib): Eliminated conflict with PPG-sw-process-id - ibtype. - -* hpath.el (hpath:is-p): Fixed error triggered when tried to format a path - with more than one %s. - -Wed Dec 4 13:39:09 1996 Bob Weiner - -* kotl/kmenu.el (id-menubar-kotl): Fixed so this mode menu is properly - installed under InfoDock. - -Tue Nov 26 21:21:50 1996 Bob Weiner - -* hui-menu.el (infodock-hyperbole-menu): Added Customization option that - sets the program used to display URLs. - -Thu Nov 14 18:11:36 1996 Bob Weiner - -* hmouse-tag.el (smart-*-at-tag-p): Modified to flash tag as a hyperbutton - when pressed, if Hyperbole has been loaded and flashing is supported - on the current device. - -* hbut.el (ibut:label-set): Made this return its LABEL argument. Useful - when label has not yet been saved in a variable. - -* kotl/klink.el (klink:at-p): Ignore HTML and SGML tags when looking for Klinks. - -Sun Nov 10 01:47:01 1996 Bob Weiner - -* wrolo.el (rolo-sort-level): Made case-insensitive. - (rolo-add): Fixed bug caused by a call to widen that sometimes - failed to leave point at the newly added entry if the rolodex - buffer was already displayed when the rolo-add call was made. - -* hmouse-tag.el (smart-lisp): Display message and beep when tag is not found. - -* hibtypes.el (function-in-buffer): -* hactypes.el (function-in-buffer): Added to follow function references - that are defined in the same buffer as the reference. - (annot-bib): - (exec-shell-cmd): - (man-show): - (rfc-toc): Updated all of these to use hpath:display-where - output display setting. - (link-to-elisp-doc): Also modified to move point to the - documentation buffer. - -* hui.el (hui:hbut-current-act): Added. - -Fri Nov 8 21:37:34 1996 Bob Weiner - -* hbut.el (ebut:act): Added for use when activating an explicit button - from a menu. - (ebut:list): Fixed bug that returned (nil) when no explicit - buttons were found. -* hui-menu.el (hui-menu-explicit-buttons): Added to display a list of - explicit buttons for activation via the Explicit-Button menu. -* hui-menu.el (hyperbole-gbut-menu): Added to display a list of existing - global buttons for activation via the Global-Button menu. - -Tue Nov 5 19:26:17 1996 Bob Weiner - -* hibtypes.el (pathname): Modified to display Emacs Lisp libraries when - given as delimited filenames, without any path. - -Fri Nov 1 00:26:13 1996 Bob Weiner - -* hui-mouse.el (hkey-alist): Moved OO-Browser handler to near bottom so - that it does not override mode-specific handlers. - -Thu Oct 31 20:01:34 1996 Bob Weiner - -* hui-mouse.el (hkey-alist): Added Action and Assist key support for Java - identifiers. -* hyperbole.el: Added Java autoloads. -* hmouse-tag.el (smart-java-package-dirs): Added this variable as the - setting of where Java package source code can be found when the - OO-Browser is not in use. Defaults to a single item list of - "${JAVA_HOME}/src/" if JAVA_HOME is set. - (smart-java-*): Added point and click identifier jumping for Java. - (smart-tags-file): Added optional argument NAME-OF-TAGS-FILE - so can search for OO-Browser lookup tables. - (smart-java-cross-reference): Added to follow @see cross-references. - -Sat Oct 26 01:05:29 1996 Bob Weiner - -* hui-menu.el (infodock-hyperbole-menu): Added Customization submenu. -* hui-mini.el (hui:menus): Added Cust/ submenu. - -* hbut.el (hbut:source): Fixed bug that neglected to account for double - quotes around the name within the printed representation of - a buffer object. - -Fri Oct 25 13:52:51 1996 Bob Weiner - -* hmouse-tag.el: Updated function to use with new buffer display protocol. -* hactypes.el: Updated many definitions here to use hpath:find and - hpath:display-buffer. -* hui-mouse.el (smart-dired): Changed call of hpath:find-other-window to - hpath:find to use new user-definable display location protocol. -* hpath.el (hpath:find): Expanded optional values of 2nd arg and made - default location of an internally displayed file be given by the - value of the hpath:display-where variable. -* hpath.el (hpath:display-buffer): - (hpath:display-buffer-other-frame): Added for linked to buffers. - (hpath:find-other-frame): Added for use in hpath:display-where-alist. -* hsite-ex.el (hpath:display-where): - (hpath:display-where-alist): - (hpath:display-buffer-alist): - Added these new variables to control where Hyperbole displays link referents. - The first one documents the possibilities and the second two specify - the function to call for each possibility. - -Tue Oct 22 01:21:53 1996 Bob Weiner - -* kotl/kvspec.el (kvspec:update-modeline): Fixed to accomodate specialized - extents in the modeline introduced by XEmacs 19.14. - -* hui-mouse.el (hkey-alist): Added support for new id-edit-mode which - can be setup to activate whenever a region is highlighted with the - mouse. When id-edit-mode is active the Action Key (or the Assist Key) - will paste the region that was highlighted at point. The key {y} also - happens to do the same thing in this mode, but has the additional - property that it will cycle through previous entries in the kill-ring. - -Fri Sep 20 22:19:33 1996 Bob Weiner - -* Changed `cs.uiuc.edu' to `xemacs.org', the new Hyperbole distribution site. - -============================================================================== -V4.02 changes ^^^^: -============================================================================== - -Fri Nov 3 22:40:34 1995 Bob Weiner - -* hsys-w3.el: Renamed entries in this file and added - action-key-url-function definition in "hyperbole.el", which can be - used to change the display function used when a URL is activated with - the Action Key. Also, loaded this library by default instead of - requiring that it be set up in "hsite.el". - -Fri Nov 3 19:25:24 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode): Fixed so re-narrows a formatted koutline - to just its cells when invoked. - -Fri Nov 3 19:29:58 1995 Bob Weiner - -* kotl/kvspec.el (kvspec:blank-lines): Modified to allow toggling blank - lines in a read-only outline and to not change the modification status - of the buffer when kvspec:toggle-blank-lines is used. - -Fri Nov 3 01:28:44 1995 Bob Weiner - -* man/hypb-mouse.txt: Updated to reflect new smart-scroll-proportional - default setting. - -* hsite-ex.el (hpath:display-alist): Fixed bug that tried to kill *info* - buffer when it didn't exist. Also fixed bug in call to Info-find-node - which gave too many args under Emacs 19. - -============================================================================== -V4.01 changes ^^^^: -============================================================================== - -Thu Nov 2 00:52:26 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:cell-help): Fixed this, the {C-c h} command - to properly deal with a cell-ref = 0. In this case, always display - the 0 cell's attributes before any other attribute data. - -* kotl/kview.el (kcell-view:previous): Fixed bug that moved to a hidden - cell when visible-p flag was given. - -Wed Nov 1 02:05:36 1995 Bob Weiner - -* kotl/klink.el (klink:parse): Changed to require a common following any - pathname in a link to prevent parsing, <3g |en>, as a pathname followed - by a viewspec. - -* kotl/kview.el (kcell-view:child): - (kcell-view:child-p) - (kcell-view:sibling-p): Added optional visible-p parameter to - find only visible matches. - -* kotl/kotl-mode.el: Fixed improper modification of global - minor-mode-alist and mode-line-format values. - -Tue Oct 31 00:45:44 1995 Bob Weiner - -* wrolo.el (rolo-mail-to): Added to compose mail to current or next e-mail - address when in a rolodex or mail buffer. Bound to {m} in rolodex - match buffer and added as Rolo/Mail menu item. - -* hsite-ex.el (smart-scroll-proportional): Changed default to t, so can do - proportional scrolling by default. Scrollbars are often available - when non-proportional scrolling is desired. - -* kotl/kotl-mode.el (kotl-mode:to-valid-position): Optimized a bit further. - -Mon Oct 30 01:37:31 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:copy-to-buffer): Made the default buffer to - copy to the buffer in the other window of this frame, if any. Also - fixed bug that caused more than one tree to be copied if there was no - successor for the tree but there was a following higher level cell. - -* hsys-www.el: Removed this library that encapsulated the old CERN - command-line WWW browser. No one would want to use that today. Use - hsys-w3.el instead. - -* hypb.el (hypb:insert-region): Added to deal with region copying used by - hmail:region and kotl-mode:copy-to-buffer. - -* kotl/kview.el (kcell-view:child-p): Added. - -* wrolo.el (rolo-isearch): Added to search for next occurrence of current - match regexp and then allow user to add characters to narrow the - search, bound to {M-s}. -* man/hyperbole.texi (Rolo Keys): Documented {M-s} binding. - -* kotl/kview.el (kcell-view:contents): Added optional POS argument. - -* kotl/kimport.el (kimport:file): Added to import different file types - based upon buffer name suffixes. Default is to import as text. - -* kotl/kimport.el: Rewrote all of these functions to handle importation - at an arbitrary level in an existing koutline. - -Sun Oct 29 01:26:25 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:demote-tree): - (kotl-mode:promote-tree): Fixed bug that could leave - point in a non-editable portion of a koutline. - -* hibtypes.el (grep-msg): Added support for IBM AIX xlc C compiler errors. - Also made this higher priority that `pathname' implicit button type so - that if activate within a doubly quoted pathname followed by a line - number, the line number is used. - -* kotl/kotl-mode.el (kotl-mode:fill-paragraph): Fixed bugs that kept it - from filling paragraphs where point was not on the first paragraph - line but the first line did not need filling. - -* hui-mini.el (Win/PopRing): - (Win/YankRing): Changed so they redisplay the Win menu. - This lets you repeatedly yank or pop window configurations until you reach - the one you want. - -* kotl/kview.el (kcell-view:create): Fixed so if no-fill is in the kcell's - attribute list, rather than passed in as the `no-fill' argument, its - value is still used. - -* kotl/kotl-mode.el (kotl-mode:add-cell): Added extra argument so can pass - in a list of attributes for the cell, as a property list. - (kotl-mode:split-cell): Fixed so original cell - attributes are propagated to the newly created cell. - -* kotl/kfile.el (kfile:create): Modified to handle importation of a - foreign text buffer when kotl-mode calls this function within a - foreign format buffer. - -Sat Oct 28 02:32:12 1995 Bob Weiner - -* kotl/klink.el (klink:create): - (link-to-kotl): - (klink:parse): - (klink:cell-ref-regexp): -* kotl/kvspec.el (kvspec:string-format): -* hactypes.el (link-to-kcell): -* kotl/kotl.el (kcell:ref-to-id): -* kotl/kotl-mode.el (kotl-mode:goto-cell): Changed viewspec preface - character from : to |. Augment viewspec characters preceded by a - colon are ignored, for now. - -Fri Oct 27 15:16:11 1995 Bob Weiner - -* kotl/kview.el (kview:set-label-separator): Rewrote so properly changes - the separator in the current view. Made it interactive and removed - input argument, kview. Use local buffer value of kview instead. - Added key binding for it, {C-c M-l}. -* kotl/kprop-em.el: - kotl/kprop-xe.el (kproperty:replace-separator): Added, called by above - function. - -* kotl/kprop-xe.el (kproperty:properties): Changed definition since - text-properties-at did not return the list of kproperties. - -Thu Oct 26 00:06:49 1995 Bob Weiner - -* hui-mini.el (hui:menus): Simplified a number of documentation display - entries. - -* kotl/kotl.el (kcell:read-only-attributes): Added, lists cell attributes - that may not be modified by a user. - -* kotl/kotl-mode.el (kotl-mode:insert-file-contents): Renamed from - kotl-mode:insert-file. Now use that name to import a file as a - sequence of sibling cells, rather than one monolithic cell, bound to - {C-x i}, overloading the standard insert-file. - (kotl-mode:get-cell-attribute): Added. - (kotl-mode:set-cell-attribute): Added, bound to {C-c C-i}. - (kotl-mode:cell-help): Renamed from :kcell-help. - (kotl-mode:print-attributes): Renamed from :print-properties. - -* kotl/klabel.el (klabel:level): Added to compute the level of a given label. - (klabel:level-alpha): Renamed from kimport:aug-label-level. - (klabel:level-legal): Added. - -* kotl/kimport.el (kimport:kcells): Added to insert kcell contents from - one koutline to another. - (kimport:text): Generalized greatly so can import into - an existing or non-existing koutline and can take buffer, buffer-name or - file arguments. - (kimport:aug-post-outline): - (kimport:star-outline): Fixed and speeded up. Code had - somehow broken over time. - (kimport:text): - (kimport:text-cells): Added to import text paragraph as - cells all at the same level. - -Wed Oct 25 02:24:35 1995 Bob Weiner - -* kotl/kfile.el (kfile:update): Added kotl-mode setting to the first line - of koutline files so they are read in with the right mode even if they - do not have a file suffix of .kotl. - (kfile:read-name): Relaxed to allow files without .kotl suffix. - -* kotl/kotl-mode.el (kfile:write): Fixed bug that failed to restore local - hook settings after renaming buffer. This would cause invalid - koutlines to be written after a rename. -* (kotl-mode): Fixed bug that treated a koutline that - has been read in and formatted for editing as an unformatted koutline. - -* hibtypes.el (text-toc): - hactypes.el (text-toc): Added to use README table of contents as - implicit buttons. - -* hbut.el (ibut:label-set): Expanded doc string. - -* README: Rewrote installation instructions. -* man/hyperbole.texi: Reorganized manual for clarity. Added obtaining - Hyperbole, installing it and filled out the whole Hyperbole Outliner - chapter. - -Tue Oct 24 03:52:40 1995 Bob Weiner - -* man/hyperbole.texi (Configuration): Renamed from Initializing. - -Mon Oct 23 01:00:54 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:top-cells): Simplified and fixed to utilize - blank lines setting. - -* kotl/kmenu.el (id-popup-kotl-menu): - (id-menubar-kotl): Added View Menu and moved view-related - tree operations from Tree menu to here. Also added Find and - Find-Read-Only menu entries so can edit/view other koutlines. - Added Append-Cell and Set-Cell-Attributes menu items. -* hui-mini.el (hui:menus): Renamed Otl/Below to Otl/Downto so could add - Otl/Blanks to toggle blanks on and off. Changed name and function of - Otl/View to Otl/Vspec. Now prompts for and activates a view spec. - User can use {C-x C-r} to view a koutline instead. - -* README: Updated What's New section to V4.00. - -* man/hyperbole.texi (Hyperbole Views): Rewrote and expanded to explain - new view specs. - -* man/hyperbole.texi (Hook Variables): - wrolo.el (rolo-yank): - (wrolo-yank-reformat-function): Added this variable to - allow user to reformat yanked entries. - -* kotl/kvspec.el (kvspec:toggle-blank-lines): Added, bound to {C-c b}. - -* kotl/kfile.el (kfile:read-v4): Added for V4 format which initializes - view spec local variables read from the file. - (kfile:update): Save current viewspec to file. - (kfile:version): Updated file format to V4.0. - -* kotl/kotl.el (kcell:ref-to-id): - kotl/kotl-mode.el (kotl-mode:goto-cell): Fixed to ignore relative specs - and to utilize view specs. - -* kotl/EXAMPLE.kotl: Updated to explain view spec handling. - -Sun Oct 22 00:38:45 1995 Bob Weiner - -* hbut.el (ebut:key-src): Fixed bug that prevented match to - hbut:source-prefix line when in a collapsed outline line. - rolo-edit-entry would not work when rolodex match entries were - collapsed. - -* kotl/kotl-mode.el (kotl-mode:append-cell): Added to append the contents - of one cell to another, bound to {C-c +}. - -* kotl/kvspec.el: Added this file to control Koutliner view specification. - (kvspec:activate): Added to interactively set view specs - and bound to {C-c C-v}. - (kvspec:no-blank-lines): Renamed from kotl-mode:shorten-all. - (kvspec:blank-lines): Renamed from kotl-mode:extend-all. - -* kotl/kmenu.el (kotl-menubar-menu): - hui-menu.el (hyperbole-menubar-menu): - wrolo-menu.el (wrolo-menubar-menu): Fixed bug when current-menubar was - nil, would not display menubar entry under Emacs 19 even though it should. - -Sat Oct 21 01:07:32 1995 Bob Weiner - -* kotl/kview.el (kview:default-blank-lines): - (kview:default-levels-to-show): - (kview:default-lines-to-show): Added these variables. - (kview:create): Use their values. - (kcell-view:create): Use kview's blank-lines setting. - -* kotl/kprop-xe.el (kproperty:remove): Fixed bug that ignored open-ended - properties. - kotl/kprop-em.el (kproperty:remove): Rewrote to remove only those - properties with matching values. - -* kotl/kotl-mode.el (kotl-mode:extend-all): - (kotl-mode:shorten-all): Rewrote to use invisible - properties. -* kotl/kfile.el (kfile:shorten-after-saving): - (kfile:extend-before-save): Removed. No longer needed - since blank lines are removed using invisible characters. - -* kotl/kprop-em.el (kproperty:put): -* kotl/kprop-xe.el (kproperty:put): Changed calling interface to take a - list of properties. - -* kotl/kfill.el (kfill:prefix-table): Generalized supercite citation prefix. - -Tue Oct 17 01:21:37 1995 Bob Weiner - -* hinit.el (hyperb:check-dir-user): Call make-directory function if - available. - -Mon Oct 16 01:02:19 1995 Bob Weiner - -* wrolo.el (rolo-file-list): Set to c:/_rolodex.otl under MS-DOS and Windows. -* hbmap.el (hbmap:dir-user): Set to c:/_hyperb/ under MS-DOS and Windows. -* hbut.el (hattr:filename): Set to _hypb under MS-DOS and Windows. - -Sun Oct 15 17:32:46 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:copy-region-as-kill): Don't trigger error - when called in a read-only buffer. - -Fri Oct 6 12:56:57 1995 Bob Weiner - -* hui-mouse.el (hkey-alist): Moved Smart Menu display code closer to - highest priority so that hkey-always-display-menu works as advertised. - -* hui-window.el (hmouse-modeline-depress): Fixed so does not false under - Emacs 19 when depress in a minibuffer window. This fixes the problem - of the Action Key not properly selecting Hyperbole minibuffer menu items. - -Thu Oct 5 14:31:56 1995 Bob Weiner - -* hui-menu.el (hyperbole-menubar-menu): Added omitted (require 'lmenu) for - Emacs 19 that prevented Hyperbole menubar from appearing under Emacs 19. - -Wed Oct 4 12:41:24 1995 Bob Weiner - -* hsite-ex.el (hkey-always-display-menu): Added this definition to prevent - it from being unbound if smart-menu is invoked and the Smart Menu system - is loaded under InfoDock. - -Wed Sep 27 01:56:53 1995 Bob Weiner - -* wrolo.el (rolo-edit): Modified to treat an empty string argument for - NAME as a null argument, so one can just hit RET interactively. Also, - modified to automatically select rolodex file when called - interactively if rolo-file-list has only one element. - -* wrolo.el (wrolo-mode-map): Added {e} binding to edit the entry at point - within the rolodex match buffer. -* man/hyperbole.texi (Rolo Keys): Documented {e} key. - -Mon Sep 25 11:15:49 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:indent-line): - (kotl-mode:indent-region): Added. Each signals an - error to force user to hit SPC to indent lines. - (kotl-mode): Set indent-line-function and - indent-region-function. - -* hyperbole.el (hmail:msg-narrow): Added autoload. - -Fri Sep 22 17:14:05 1995 Bob Weiner - -* hsite-ex.el (hpath:display-alist): Fixed bug in handling info-suffix - variable scoping that prevented Action Key from browsing info files in - dired. - -============================================================================== -V4.00 changes ^^^^: -============================================================================== diff -r f427b8ec4379 -r 41ff10fd062f lisp/hyperbole/ChangeLog.1 --- a/lisp/hyperbole/ChangeLog.1 Mon Aug 13 10:03:54 2007 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4077 +0,0 @@ -Thu Sep 21 11:44:51 1995 Bob Weiner - -* wrolo.el (rolo-name-and-email): Fixed bug that could cause current - buffer to scroll. - -Wed Sep 20 11:46:09 1995 Bob Weiner - -* hypb.el (hypb:supercite-p): Fixed bug that returned nil when should have - returned t. - (hypb:configuration): Added so this could be used in OO-Browser. -* hactypes.el (hyp-config): Simplified to just call hypb:configuration. - -============================================================================== -V3.19.09 changes ^^^^: -============================================================================== - -Fri Sep 15 12:59:40 1995 Bob Weiner - -* wrolo.el (rolo-name-and-email): Modified to work if point is in a mail - or news summary listing buffer. - -* hui-window.el (assist-key-modeline): Simplified unburying of buffer. - -Thu Sep 14 14:03:17 1995 Bob Weiner - -* hmail.el (hmail:buffer): Modified to use logic in hmail:region. - (hmail:region): - kotl/kotl-mode.el (kotl-mode:mail-tree): - (kotl-mode:copy-to-buffer): Modified to prompt for - whether to erase hidden text when copying or to copy and expand it. - -* hmouse-key.el (hmouse-set-bindings): - hmouse-sh.el - hmouse-reg.el (hmouse-setup): - (hmouse-get-bindings): Execute these even if on a tty when - under Emacs 19, XEmacs or InfoDock. - -* hmouse-key.el (hmouse-shift-buttons): Added this function to allow - switching the location of the Action and Assist Keys between shifted - and unshifted mouse buttons. -* man/hyperbole.texi (Smart Keys): Documented this new function. - -* hactypes.el (link-to-Info-node): Removed hpath:validate call since that - will cause some valid node references to not be accepted. - -Wed Sep 13 13:23:24 1995 Bob Weiner - -* kotl/kfill.el: Renamed most functions from filladapt- to kfill:, to - avoid conflicts with the new minor mode filladapt. -* kotl/kotl-mode.el (kotl-mode): Turn filladapt minor mode off since - "kfill.el" handles filling in koutlines and reload kfill if some other - package has defined fill-paragraph. - -* hpath.el (hpath:find): -* hactypes.el (exec-shell-cmd): Execute in selected window if in the - OO-Browser, even when other-window is requested. - -* hmous-info.el (Info-handle-in-node-hdr): - (Info-handle-in-menu): Fixed invalid call to - Info-goto-node under GNU Emacs. - -* DEMO (Implicit Path Links): Expanded explanation of pathname handling. -* hibtypes.el (pathname): Added doc pointers to variables that control the - way files are displayed. - -* hpath.el (hpath:exists-p): - (hpath:suffixes): Added. - (hpath:find): - (hpath:validate): -* hactypes.el (link-to-Info-node): - (link-to-ebut): Modified to handle files that have been - compressed/uncompressed after a link was made to their - filenames. - -* hsite-ex.el: (hpath:display-alist): Modified to handle compressed info - files. - -Mon Sep 11 14:00:29 1995 Bob Weiner - -* hmouse-tag.el (smart-c-include-file): - (smart-asm-include-file): Fixed to display include file in - viewer window if current in the OO-Browser. - -* kotl/klink.el (klink:create): Fixed to read and parse link references - properly. -* hargs.el (hargs:at-p): Return klink as a list, not a string. - (hargs:read): Convert klink to a string after reading it. - -Wed Aug 30 16:34:34 1995 Bob Weiner - -* man/hyperbole.texi (Smart Keyboard Keys): Updated to describe URL and - gomoku support. - -* hui-mouse.el (hkey-alist): When playing {M-x gomoku}, Action key makes - human move at point and Assist Key takes back a move at point. - -============================================================================== -V3.19.08 changes ^^^^: -============================================================================== - -Sun Aug 27 04:55:17 1995 Bob Weiner - -* hibtypes.el (patch-msg): Jumps to source associated with patch output - lines that begin with "Hunk" or "Patching". - -Sat Aug 26 21:30:45 1995 Bob Weiner - -* hibtypes.el (grep-msg): Added support for Perl5 error message parsing. - -Fri Aug 25 00:30:08 1995 Bob Weiner - -* kotl/kmenu.el (id-menubar-kotl): - (id-popup-kotl-menu): Added Hide-Levels, Hide-Subtree, - Show-Subtree menu items. Also enabled Copy-Before/After-Cell menu - items. - hui-menus.el (hui:menus): Added `Below' (same as {C-x $}) and `Kill' - (same as {C-c C-k}) menu items to Outliner menu. - -============================================================================== -V3.19.07 changes ^^^^: -============================================================================== - -* hui.el (hui:ebut-buf): Support mail buffers of the form *VM-mail* or - *mail*<2>. - -* kotl/kotl-mode.el (kotl-mode:hide-sublevels): Added to hide all outline - levels deeper than a given level argument. Bound to {C-x $}, since is - similar to set-selective-display. - -* kotl/kview.el (kcell-view:next): Fixed bug that failed to advance to - next visible cell when visible-p flag was true and current cell had a - collapsed subtree but was not itself collapsed and point was not on the - final line of the cell. - -Thu Aug 24 23:32:28 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:hide-subtree): Added to hide the subtree, - excluding root of a cell. Bound to {C-M-h}. - (kotl-mode:show-subtree): Added to show the subtree, - excluding root of a cell. - -Wed Aug 23 12:34:48 1995 Bob Weiner - -* hpath.el (hpath:url-at-p): - (hpath:url-p): Fixed to handle more URL specifications and to - delete trailing periods and other characters properly. - -Tue Aug 22 12:08:53 1995 Bob Weiner - -* hui-menu.el (hyperbole-menubar-menu): - wrolo-menu.el (wrolo-menubar-menu): - kotl/kmenu.el (kotl-menubar-menu): Fixed bug that would add menu if - menubar was nil. - -============================================================================== -V3.19.06 changes ^^^^: -============================================================================== - -Wed Aug 16 12:41:09 1995 Bob Weiner - -* hibtypes.el (mail-address-regexp): Corrected omission of underscores in - addresses. - -Thu Aug 10 17:36:23 1995 Bob Weiner - -* hpath.el (hpath:at-p): Modified to handle local file URLs like - file://localhost/ just as other local file references. - -* hargs.el (hargs:delimited): Modified to accomodate long string - delimiters where point might be in the middle of the opening delimiter. - -Wed Aug 9 18:37:54 1995 Bob Weiner - -* hactypes.el (hyp-config): Reversed order of listing of Editor: and - Hyperbole: lines. - -============================================================================== -V3.19.05 changes ^^^^: -============================================================================== - -Tue Aug 8 10:53:38 1995 Bob Weiner - -* hgnus.el - hsmail.el (smail:comment-add): Add to front of hook if add-hook exists - so that if the mail/news buffer headers are highlighted, so is this - comment header. - -Mon Jul 31 15:33:29 1995 Bob Weiner - -* kotl/kview.el (kview:insert-contents): - (kcell-view:create): Moved call to kfile:narrow-to-kcells - so it is after insertion of newlines terminating the new cell. - Otherwise, this call would leave kotl data exposed when a cell was - inserted at the end of an outline. - -Tue Jul 25 16:26:16 1995 Bob Weiner - -* hibtypes.el (mail-address): Prevented from triggering in a mail or news - summary buffer. - -* hui-mouse.el: Rewrote some functions for improved clarity. - -============================================================================== -V3.19.04 changes ^^^^: -============================================================================== - -Fri Jul 14 17:03:27 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode): Changed hook used to save koutline data - from write-contents-hooks to local-write-file-hooks. - -Thu Jul 13 16:37:30 1995 Bob Weiner - -* hui-em19-b.el (hproperty:but-add): Under Emacs 19, modified to highlight - explicit buttons when mouse passes over them if - hproperty:but-emphasize-p has been set non-nil (nil = default) in - hsite.el. - -* hsmail.el (smail:comment-add): Modified to only add - "Hyperbole mail buttons accepted" comment to outgoing mail messages if - the full Hyperbole system has been loaded since this function can be - called when only hyperbole.el has been loaded by a site initialization - but the individual user never uses Hyperbole. - -Mon Jul 10 11:49:52 1995 Bob Weiner - -* hui-mouse.el (hkey-alist): -* hmouse-tag.el (smart-fortran): - (smart-fortran-at-tag-p): Added Fortran tags browsing support. - -Fri Jul 7 14:02:28 1995 Bob Weiner - -* hsite-ex.el (hpath:display-alist): Modified to display files below an - /info/ directory but with a non-info suffix, in whatever their normal - mode is. Files under /info/ without a suffix are displayed as info - files. - -* kotl/kotl-mode.el (kotl-mode:center-line): Added and bound to {M-s}. - (kotl-mode:center-paragraph): Added and bound to {M-S}. - (kotl-mode:fill-paragraph): Modified to save point as a marker. - -============================================================================== -V3.19.03 changes ^^^^: -============================================================================== - -* htz.el (htz:date-unix): Clarified default values in doc string - and fixed bug that ignored LOCAL timezone argument, leading to - improper display of outliner cell time attributes. - -* kotl/kotl.el (kotl-data:to-kcell-v2): - (kotl-data:to-kcell-v3): Rewrote to repair cells on the fly - where the cell data saved in the outline is nil. This would only - happen if there is a bug in the kproperty code, but we still want - people to be able to read in outlines without error in such a case. - -* kotl/kprop-em.el (kproperty:put): Rewrote to prevent inheritance of - the added property by characters inserted following the region to which - the property is added. This inheritance caused bugs in the cell - separator search routines. Inheritance was already off by default for - characters preceding this region. - -Thu Jul 6 14:24:40 1995 Bob Weiner - -* hmouse-drv.el (hkey-help-show): Fixed a bug that failed to properly - check whether a help buffer was already displayed. - -Sun Jun 25 17:16:21 1995 Bob Weiner - -* kotl/kimport.el (kimport:star-outline): Modified to handle start - outlines whose stars are preceded by whitespace. - -* kotl/klabel.el (klabel-type:set-star): Fixed infinite loop problem when - converting to start labels. - -* kotl/kotl-mode.el (kotl-mode:add-cell): Modified to only fill a new cell - This is called by kotl-mode:split-cell. - (kotl-mode:add-cell): Added no-fill parameter. - (kotl-mode:split-cell): Modified to not fill new cell - if the original cell had a no-fill property. - -* kotl/kview.el (kview:add-cell): Added optional parameter no-fill to skip - filling of any initial cell contents. - -Fri Jun 23 11:58:24 1995 Bob Weiner - -* hyperbole.el (Info-goto-node): Added autoload of this for Hyperbole menus. - -* kotl/klabel.el (klabel-type:set-partial-alpha): Speeded up partial-alpha - renumbering. - (klabel-type:update-tree-labels): Added, to update labels - in a single tree. - -* hvm.el (Vm-msg-to-p): Fixed problem that link-to-mail displayed the - wrong message when a folder was sorted into some order other than the - physcial order of messages. - -* kotl/kfile.el (kfile:print-to-string): Locally set emacs-lisp-mode-hook - to nil so no fontification is done when pretty printing koutline data - structures. - -============================================================================== -V3.19.02 changes ^^^^: -============================================================================== - -Wed Jun 21 00:42:12 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:fill-tree): Modified to support filling 0 - rooted tree, i.e. all cells in outline, when given a prefix argument. - -* kotl/klabel.el (klabel-type:set-labels): Fixed bug that incremented - labels by 1 too many because point started at an invalid outline - position. - -* kotl/kotl-mode.el (kotl-mode:exchange-cells): Modified to only refill - cells when kotl-mode:refill-flag is non-nil. - -* kotl/kproperty.el: Separated into two separate implementation files. - kprop-em.el for Emacs 19 - kprop-xe.el for XEmacs -* MANIFEST: -* Makefile (EL_KOTL, ELC_KOTL): Added references to new kprop-* files. - -Tue Jun 20 10:54:18 1995 Bob Weiner - -* kotl/kproperty.el (kproperty:put): Fixed XEmacs version of this function - by using raw extents instead of text properties. - -* kotl/kmenu.el (id-popup-kotl-menu): Fixed Show-Top-Level-Only to run - proper command. - -* hui-menus.el (Msg): Shortened Msg menu to fit in 80 columns. - -* kotl/kproperty.el (kproperty:map): Added to map over a matching property - in a buffer and to return the result. - -Mon Jun 19 18:50:34 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:demote-tree): - (kotl-mode:promote-tree): - (kotl-mode:move-after): - (kotl-mode:move-before): -* kotl/kview.el (kview:move): Reversed meaning of last argument, fill-p. - -* hui-menus.el (hui:menus): Removed any leading 0 from Hyperbole version - number in the keyboard menu. - -============================================================================== -V3.19.01 changes ^^^^: -============================================================================== - -Thu Jun 15 00:24:34 1995 Bob Weiner - -* kotl/kview.el (kcell-view:previous): Expanded cases that will find - previous cell. - -* kotl/kotl-mode.el (kotl-mode:move-after): - (kotl-mode:move-before): Fixed bug where original - sibling cell could be renumbered twice, the 2nd time with the wrong label. - -* hui-menus.el (hui:menu-enter): Rewrote to properly handle XEmacs and - Emacs 19 keyboard events. - -* kotl/kview.el (kcell-view:previous): - (kcell-view:next): Optimized. - -Wed Jun 14 01:49:45 1995 Bob Weiner - -* kotl/kview.el (kview:goto-cell-id): Speeded up by up to 10x with - optimized implementations for each Emacs variant. - -* kotl/kotl-mode.el (kotl-mode:fill-cell): Notify user if can't fill since - cell has a no-fill attribute. - -* kotl/EXAMPLE.kotl (2b5): Explained cell and tree filling. - -* hversion.el (id-browse-file): Added definition needed by pull-down menu. - -* kotl/kotl-mode.el (kotl-mode:fill-tree): Added and bound to {C-M-j} and - {C-M-q}. - -* kotl/kview.el (kcell-view:remove-attr): - kotl/kotl.el (kcell:remove-attr): - kotl/knode.el (knode:remove-attr): Added. - -* kotl/kview.el (kcell-view:set-attr): Added this back in; somehow it was - accidentally deleted. Also made it and kcell-view:get-attr - interactive, so users can set and get attributes. - -* kotl/kotl-mode.el (kotl-mode:demote-tree): - (kotl-mode:promote-tree): With prefix ARG = 0, cells - are moved up to one level but are not refilled. This is much faster - than when each cell must be refilled. - -* kotl/kview.el (kview:move): Optimized to skip mapping over a tree to - re-collapse cells if none were collapsed. - -Tue Jun 13 16:35:42 1995 Bob Weiner - -* hmous-info.el (Info-handle-in-note): Added support for `See' - cross-references used by XEmacs. - -============================================================================== -V3.19 changes ^^^^: -============================================================================== - -Tue Jun 13 16:35:42 1995 Bob Weiner - -* hinit.el (hyperb:init-menubar): -* hui-menu.el (hyperbole-menubar-menu): Modified to re-install Hyperbole - menu in InfoDock menubar after using the menu's Quit item. - -Mon Jun 12 19:31:28 1995 Bob Weiner - -* kotl/klabel.el (klabel-type:set-alpha): Optimized alpha and legal - renumbering. Cut time by about 50% for multi-level outlines. - -Tue Jun 6 12:34:47 1995 Bob Weiner - -* kotl/klabel.el - kview.el - kotl-mode.el: Optimized many functions to not compute - label-sep-len repeatedly. This speeds up many operations. - -* kotl/kotl-mode.el (kotl-mode-map): Fixed to handle {M-q} bound to - fill-paragraph-or-region in XEmacs. - -Mon Jun 5 16:56:58 1995 Bob Weiner - -* hui-menu.el (infodock-hyperbole-menu): Made "Quit" menu item remove - Hyperbole comment from future outgoing mail and remove Hyperbole menu - from every menubar which has it. - -============================================================================== -V3.18.13 changes ^^^^: -============================================================================== - -Fri Jun 2 11:29:11 1995 Bob Weiner - -* kotl/kotl-mode.el (kotl-mode:beginning-of-tree): Added and bound to {C-c ^}. - (kotl-mode:end-of-tree): Addded and bound to {C-c $}. - -* kotl/kview.el (kcell-view:parent): Added optional parameter visible-p, - when non-nil, only visible parents are considered. - -* kotl/kotl-mode.el (kotl-mode:first-sibling): Added and bound to {C-c <}. - (kotl-mode:last-sibling): Added and bound to {C-c >}. - -* man/hyperbole.texi (Outliner Keys): - kotl/kotl-mode.el (kotl-mode:copy-to-buffer): Added and bound to {C-c M-c}. - -Thu Jun 1 11:10:03 1995 Bob Weiner - -* hui-window.el (smart-window-of-coords): - (smart-coords-in-window-p): - (hmouse-modeline-resize-window): Fixed bug under XEmacs 19.11. - -============================================================================== -V3.18.12 changes ^^^^: -============================================================================== - -Fri May 19 15:32:37 1995 Bob Weiner - -* hui-menus.el (hyperbole): Added call to hyperb:init-menubar. -* hinit.el (hyperb:init-menubar): Added to add Hyperbole menu to menubar. -* hui-menu.el (infodock-hyperbole-menu): Added Quit menu item to delete - the Hyperbole menu from the menubar. {C-h h} will bring it back again. - -Thu May 18 12:23:01 1995 Bob Weiner - -* Changed all cs.brown references to hub.ucsb.edu (for mail lists) - and cs.uiuc.edu (for Hyperbole source). - -* hui-xe-but.el (hproperty:set-item-highlight): Fixed this function - for use with XEmacs 19.12. - -* wrolo.el (rolo-to): - (rolo-edit): Fixed longstanding bug that failed to move point - to the matched entry if the rolodex file buffer was already displayed - before the edit request was made. - -============================================================================== -V3.18.11 changes ^^^^: -============================================================================== - -Mon May 15 11:20:38 1995 Bob Weiner - -* hmous-info.el (Info-handle-in-node-hdr): - (Info-handle-in-menu): Fixed to handle Info references - whose filenames require a suffix in Info-suffix-list. - -* hpath.el (hpath:find-program): Return nil if given a directory name, so - that no special cases trigger on directories. - -* hsite-ex.el (hpath:display-alist): Changed to display files which do not - end in .info but which are in directories /info/ or /info-local/ as - Info files. - -============================================================================== -V3.18.10 changes ^^^^: -============================================================================== - -Fri May 12 12:54:19 1995 Bob Weiner - -* Makefile (dist): Updated to execute entire distribution build process. - -* hsite-ex.el (hyperb:lemacs-p): -* hui-xe-but.el (hproperty:highlight-face): Fixed to highlight explicit - buttons and rolodex matches with the `italic' face when used under - XEmacs on a tty. - -============================================================================== -V3.18.9 changes ^^^^: -============================================================================== - -Tue May 9 12:45:21 1995 Bob Weiner - -* Makefile (install): Changed to install documentation. - -* man/hyperbole.texi (Smart Keys): Renamed hmouse-doc.txt to - hypb-mouse.txt for easier association with Hyperbole when moved to - data-directory during install. -* hypb.el (hypb:mouse-help-file): Added to centralize resolution of - the hypb-mouse.txt path. -* hmouse-drv.el (hkey-summarize): -* hui-menu.el (infodock-hyperbole-menu): -* hui-menus.el (hui:menus): Called (hypb:mouse-help-file). - -* hui-window.el (smart-coords-in-window-p): - (smart-window-of-coords): Updated to support XEmacs 19.12 - mouse-position protocol which returns window of event as the car of a - list. - -* hibtypes.el (debugger-source): Added jump to source of an XEmacs - assertion failure which looks like: - assert_failed (file=0xf3c78 "eval.c", line=1412, - -Mon May 8 14:30:56 1995 Bob Weiner - -* man/hyperbole.texi (Operating Menus): -* hui-menu.el (hyperbole-menubar-menu): -* kotl/kfile.el: -* kotl/kmenu.el (kotl-menubar-menu): -* wrolo.el (wrolo-mode): -* wrolo-menu.el (wrolo-menubar-menu): Added support for pulldown and popup - menus under Emacs19. - -* kotl/kotl-mode.el (kotl-mode:print-properties): Made kview argument - required to avoid a bug where kview is somehow set to nil within - callers. - -* kotl/kview.el (kcell-view:to-label-end): Clarified error when kview is nil. - -============================================================================== -V3.18.8 changes ^^^^: -============================================================================== - -Fri May 5 14:33:51 1995 Bob Weiner - -* Makefile: Removed building of Info and Postscript versions of the - Hyperbole manual from default `make'. Use `make info' and `make ps', - respectively. - -* hui-xe-but.el: -* wrolo.el (rolo-highlight-face): Adapted for new XEmacs make-face return - value of a face object, rather than the old behavior of a face name. - -* kotl/kfile.el (kfile:update): Added (let ((debug-on-error nil)) so one - can easily save koutlines while debugging Emacs Lisp code. - -Tue May 2 11:08:53 1995 Bob Weiner - -* Makefile (tags): Replaced all - with underscore in variable names to - satisfy the AIX sh. - -Mon May 1 15:50:33 1995 Bob Weiner - -* hsite-ex.el (hpath:display-alist): Added display of top node when Action - Key is pressed over an Info file name. - -Fri Apr 28 19:18:13 1995 Bob Weiner - -* hui-xe-but.el (hproperty:set-item-highlight): Fixed failure to set - rolo-highlight-face when it is the same as the default font. - -============================================================================== -V3.18.7 changes ^^^^: -============================================================================== - -Mon Apr 24 10:49:30 1995 Bob Weiner - -* hui-mouse.el (hkey-alist): Simplified support for view major and minor - modes. - -Sun Apr 23 13:21:20 1995 Bob Weiner - -* hibtypes.el (debugger-source): Renamed from gdb-source and added dbx and - xdb debugger support for jumping to source from a stack backtrace line. - -Wed Apr 19 19:37:20 1995 Bob Weiner - -* hmouse-tag.el (smart-tags-file-path): Added this function, used by - ibtype gdb-source and actype link-to-file-line to find non-local, - relative files. -* hyperbole.el (smart-tags-file-path): Added autoload. - -Tue Apr 18 11:49:27 1995 Bob Weiner - -* hversion.el (id-tool-invoke): Fixed to handle interactive command calls. - -Sun Apr 16 22:35:33 1995 Bob Weiner - -* hversion.el (sm-window-sys-term): Support Emacs under OS/2 which uses - the Presentation Manger window manager. -* htz.el (htz:local): OS/2 doesn't have a date function, so use TZ or - TIMEZONE environment variable if set as local timezone instead. -* hpath.el (hpath:url-p): - (hpath:url-at-p): Avoid [a-z]:/path patterns since these may be - disk paths on OS/2, DOS or Windows. - -============================================================================== -V3.18.6 changes ^^^^: -============================================================================== - -Fri Apr 14 15:31:17 1995 Bob Weiner - -* man/hyperbole.ps: Removed from the distribution. Too large; users who - need it can build it themselves. - -* man/hyperbole.texi (Action Types): Documented extension command - characters' use of `+' prefix. - -* hargs.el (hargs:iforms): Added basic support for new Emacs 19 `K' - command character. - -* *.el: Added KEYWORDS: header. - -Wed Apr 12 11:26:03 1995 Bob Weiner - -* hui-window.el (smart-coords-in-window-p): - (smart-window-of-coords): Fixed to work with XEmacs 19.11 - which can return nil for (event-window) if event is over a - modeline. - -Tue Apr 11 12:48:18 1995 Bob Weiner - -* hargs.el (hargs:get): Added support for user extension interactive - command characters that are being added to Emacs 19. Each such - character is preceded by a `+' character. - -* hui-mouse.el (hkey-alist): Added Action/Assist key press support for - OO-Browser listing buffers used when the full OO-Browser user interface - is not displayed. - -Mon Apr 10 17:41:54 1995 Bob Weiner - -* Makefile (ELC-COMPILE): Added hsys-* files so they will be built. - -============================================================================== -V3.18.5 changes ^^^^: -============================================================================== - -Sat Apr 8 13:53:27 1995 Bob Weiner - -* man/hyperbole.texi (Top): Added credits. - -Fri Apr 7 17:21:04 1995 Bob Weiner - -* kotl/kfile.el (kfile:update): - kotl/kotl.el (kotl-data:create): Modified to repair invalid cells when - trying to save them. - (kotl-data:to-kcell-v3): Modified to repair invalid cells when - trying to load them from a file. - -Thu Apr 6 10:22:07 1995 Bob Weiner - -* Makefile (PRELOADS): Added ref to $(SITE-PRELOADS) for customization of - the Lisp libraries loaded before byte-compiling any files. - (BATCHFLAGS): Removed -no-site-file so addition of the - OO-Browser directory to load-path may be done in site-start.el. - -* kotl/kmenu.el: Added this file of menus for the Koutliner from InfoDock - and adapted for use under standard XEmacs. - -Wed Apr 5 18:48:15 1995 Bob Weiner - -* hinit.el (hyperb:init): Added setup of XEmacs pulldown menu for Hyperbole. -* hui-menu.el: Added this file to provide a global pulldown menu of InfoDock - comands under XEmacs. -* wrolo-menu.el: Added this file of menus for the Rolodex from InfoDock - and adapted for use under standard XEmacs. Also defines a rolodex - menu which may be used independently of the Hyperbole menu. - -Mon Apr 3 10:03:09 1995 Bob Weiner - -* hyperbole.el (rolo-word): Autoloaded this command. - -============================================================================== -V3.18.4 changes ^^^^: -============================================================================== - -Tue Mar 28 12:22:27 1995 Bob Weiner - -* hui-window.el (hmouse-release-left-edge): - (hmouse-release-right-edge): Fixed bug which improperly - called `window-event' when `event-window' was intended. - -Sun Mar 26 00:39:18 1995 Bob Weiner - -* man/hyperbole.texi: Renamed from hypb.texi. - -Sat Mar 25 23:20:02 1995 Bob Weiner - -* Makefile (elc): Cleaned up user output produced by this target. - -============================================================================== -V3.18.3 changes ^^^^: -============================================================================== - -Fri Mar 24 10:41:17 1995 Bob Weiner - -* hibtypes.el (rfc): Updated to support efs too. -* hpath.el (hpath:ange-ftp-p): - (hpath:ange-ftp-at-p): Added support for `efs' package, the - successor to ange-ftp. - Also changed so can jump to remote pathnames if ange-ftp will - be autoloaded via file-name-handler-alist under Emacs V19. - -* Makefile (elc): Rewrote in a portable manner so that one emacs - invocation builds all elc files. - -Thu Mar 23 03:23:51 1995 Bob Weiner - -* kotl/klink.el (klink:at-p): Fixed so won't trigger in OO-Browser listing - buffers, e.g. on a C++