changeset 109196:f779e6dd2626

Merge from mainline.
author Katsumi Yamaoka <katsumi@flagship2>
date Tue, 18 May 2010 11:35:42 +0000
parents 1bbf35fc0d68 (current diff) 6b0a523f9990 (diff)
children f3352dc3107f
files
diffstat 24 files changed, 1020 insertions(+), 128 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon May 17 12:37:57 2010 +0000
+++ b/ChangeLog	Tue May 18 11:35:42 2010 +0000
@@ -1,3 +1,21 @@
+2010-05-18  Glenn Morris  <rgm@gnu.org>
+
+	* configure.in (POST_ALLOC_OBJ) [cygwin]: Omit vm-limit.o.
+	(POST_ALLOC_OBJ) [!cygwin]: Set to empty.
+
+	* config.bat (RALLOC_OBJ): Edit to empty if sys_malloc.
+	* configure.in (REL_ALLOC): Unset on gnu, gnu-linux if DOUG_LEA_MALLOC.
+	(RALLOC_OBJ): New output variable.
+
+	* config.bat (GMALLOC_OBJ, VMLIMIT_OBJ): Edit to empty if sys_malloc.
+	* configure.in (GMALLOC_OBJ, VMLIMIT_OBJ): New output variables.
+
+2010-05-17  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* Makefile.in (src): Provide the name of the VCS file that witnesses
+	a pull.
+	($(srcdir)/src/config.in): Handle accidental removal of src/config.in.
+
 2010-05-17  Glenn Morris  <rgm@gnu.org>
 
 	* configure.in (OLDXMENU_DEPS): New output variable.
--- a/Makefile.in	Mon May 17 12:37:57 2010 +0000
+++ b/Makefile.in	Tue May 18 11:35:42 2010 +0000
@@ -335,9 +335,13 @@
 	      CC='${CC}' CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}'         \
 	      LDFLAGS='${LDFLAGS}' MAKE='${MAKE}' BOOTSTRAPEMACS="$$boot"; \
 	fi;
+	if [ -r .bzr/checkout/dirstate ]; then 			\
+	    vcswitness="$$(pwd)/.bzr/checkout/dirstate"; 	\
+	fi; 							\
 	cd $@; $(MAKE) all $(MFLAGS)                           \
 	  CC='${CC}' CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}' \
-	  LDFLAGS='${LDFLAGS}' MAKE='${MAKE}' BOOTSTRAPEMACS=""
+	  LDFLAGS='${LDFLAGS}' MAKE='${MAKE}' BOOTSTRAPEMACS=""	\
+	  VCSWITNESS="$$vcswitness"
 
 blessmail: Makefile src FRC
 	cd lib-src; $(MAKE) maybe-blessmail $(MFLAGS) \
@@ -369,7 +373,11 @@
 	cd ${srcdir} && autoconf
 
 $(srcdir)/src/config.in: $(srcdir)/src/stamp-h.in
-	@true
+	@ # Usually, there's no need to rebuild src/config.in just
+	@ # because stamp-h.in has changed (since building stamp-h.in
+	@ # refreshes config.in as well), but if config.in is missing
+	@ # then we really need to do something more.
+	[ -r "$@" ] || ( cd ${srcdir} && autoheader )
 $(srcdir)/src/stamp-h.in: $(AUTOCONF_INPUTS)
 	cd ${srcdir} && autoheader
 	rm -f $(srcdir)/src/stamp-h.in
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/admin/notes/bzr	Tue May 18 11:35:42 2010 +0000
@@ -0,0 +1,40 @@
+NOTES ON COMMITTING TO EMACS'S BAZAAR REPO    -*- outline -*-
+
+* Install changes only on one branch, let them get merged elsewhere if needed.
+In particular, install bug-fixes only on the release branch (if there
+is one) and let them get synced to the trunk; do not install them by
+hand on the trunk as well.  E.g. if there is an active "emacs-23" branch
+and you have a bug-fix appropriate for the next Emacs-23.x release,
+install it only on the emacs-23 branch, not on the trunk as well.
+
+Installing things manually into more than one branch makes merges more
+difficult.
+
+http://lists.gnu.org/archive/html/emacs-devel/2010-03/msg01124.html
+
+* Backporting a bug-fix from the trunk to a branch (e.g. "emacs-23").
+Label the commit as a backport, e.g. by starting the commit message with
+"Backport:".  This is helpful for the person merging the release branch
+to the trunk.
+
+http://lists.gnu.org/archive/html/emacs-devel/2010-05/msg00262.html
+
+* Installing changes from your personal branches.
+If your branch has only a single commit, or many different real
+commits, it is fine to do a merge.  If your branch has only a very
+small number of "real" commits, but several "merge from trunks", it is
+preferred that you take your branch's diff, apply it to the trunk, and
+commit directly, not merge.  This keeps the history cleaner.
+
+In general, when working on some feature in a separate branch, it is
+preferable not to merge from trunk until you are done with the
+feature.  Unless you really need some change that was done on the
+trunk while you were developing on the branch, you don't really need
+those merges; just merge once, when you are done with the feature, and
+Bazaar will take care of the rest.  Bazaar is much better in this than
+CVS, so interim merges are unnecessary.
+
+Or use shelves; or rebase; or do something else.  See the thread for
+yet another fun excursion into the exciting world of version control.
+
+http://lists.gnu.org/archive/html/emacs-devel/2010-04/msg00086.html
--- a/config.bat	Mon May 17 12:37:57 2010 +0000
+++ b/config.bat	Tue May 18 11:35:42 2010 +0000
@@ -201,6 +201,13 @@
 rm -f makefile.tmp
 :src5
 
+if "%sys_malloc%" == "" goto src5a
+sed -e "/^GMALLOC_OBJ *=/s/gmalloc.o//" <Makefile >makefile.tmp
+sed -e "/^VMLIMIT_OBJ *=/s/vm-limit.o//" <makefile.tmp >makefile.tmp2
+sed -e "/^RALLOC_OBJ *=/s/ralloc.o//" <makefile.tmp2 >Makefile
+rm -f makefile.tmp makefile.tmp2
+:src5a
+
 if "%nodebug%" == "" goto src6
 sed -e "/^CFLAGS *=/s/ *-gcoff//" <Makefile >makefile.tmp
 sed -e "/^LDFLAGS *=/s/=/=-s/" <makefile.tmp >Makefile
--- a/configure	Mon May 17 12:37:57 2010 +0000
+++ b/configure	Tue May 18 11:35:42 2010 +0000
@@ -724,6 +724,8 @@
 NS_SUPPORT
 LIB_STANDARD
 HAVE_XSERVER
+GMALLOC_OBJ
+VMLIMIT_OBJ
 RSVG_CFLAGS
 RSVG_LIBS
 GTK_CFLAGS
@@ -810,6 +812,7 @@
 LIBXMENU
 LIBX_OTHER
 OLDXMENU_DEPS
+RALLOC_OBJ
 CYGWIN_OBJ
 PRE_ALLOC_OBJ
 POST_ALLOC_OBJ
@@ -10513,11 +10516,20 @@
 if test $emacs_cv_var___after_morecore_hook = no; then
   doug_lea_malloc=no
 fi
+
 if test "${system_malloc}" = "yes"; then
   GNU_MALLOC=no
   GNU_MALLOC_reason="
     (The GNU allocators don't work with this system configuration.)"
-fi
+  GMALLOC_OBJ=
+  VMLIMIT_OBJ=
+else
+  test "$doug_lea_malloc" != "yes" && GMALLOC_OBJ=gmalloc.o
+  VMLIMIT_OBJ=vm-limit.o
+fi
+
+
+
 if test "$doug_lea_malloc" = "yes" ; then
   if test "$GNU_MALLOC" = yes ; then
     GNU_MALLOC_reason="
@@ -10528,6 +10540,14 @@
 #define DOUG_LEA_MALLOC 1
 _ACEOF
 
+
+  ## Use mmap directly for allocating larger buffers.
+  ## FIXME this comes from src/s/{gnu,gnu-linux}.h:
+  ## #ifdef DOUG_LEA_MALLOC; #undef REL_ALLOC; #endif
+  ## Does the AC_FUNC_MMAP test below make this check unecessary?
+  case "$opsys" in
+    gnu*) REL_ALLOC=no ;;
+  esac
 fi
 
 if test x"${REL_ALLOC}" = x; then
@@ -26520,6 +26540,7 @@
 _ACEOF
 
 fi
+
 if test "${GNU_MALLOC}" = "yes" ; then
 
 cat >>confdefs.h <<\_ACEOF
@@ -26527,12 +26548,16 @@
 _ACEOF
 
 fi
+
+RALLOC_OBJ=
 if test "${REL_ALLOC}" = "yes" ; then
 
 cat >>confdefs.h <<\_ACEOF
 #define REL_ALLOC 1
 _ACEOF
 
+
+  test "$system_malloc" != "yes" && RALLOC_OBJ=ralloc.o
 fi
 
 
@@ -26540,11 +26565,11 @@
   CYGWIN_OBJ="sheap.o"
   ## Cygwin differs because of its unexec().
   PRE_ALLOC_OBJ=
-  POST_ALLOC_OBJ="lastfile.o vm-limit.o"
+  POST_ALLOC_OBJ=lastfile.o
 else
   CYGWIN_OBJ=
   PRE_ALLOC_OBJ=lastfile.o
-  POST_ALLOC_OBJ="\$(vmlimitobj)"
+  POST_ALLOC_OBJ=
 fi
 
 
--- a/configure.in	Mon May 17 12:37:57 2010 +0000
+++ b/configure.in	Tue May 18 11:35:42 2010 +0000
@@ -1592,11 +1592,20 @@
 if test $emacs_cv_var___after_morecore_hook = no; then
   doug_lea_malloc=no
 fi
+
 if test "${system_malloc}" = "yes"; then
   GNU_MALLOC=no
   GNU_MALLOC_reason="
     (The GNU allocators don't work with this system configuration.)"
+  GMALLOC_OBJ=
+  VMLIMIT_OBJ=
+else
+  test "$doug_lea_malloc" != "yes" && GMALLOC_OBJ=gmalloc.o
+  VMLIMIT_OBJ=vm-limit.o
 fi
+AC_SUBST(GMALLOC_OBJ)
+AC_SUBST(VMLIMIT_OBJ)
+
 if test "$doug_lea_malloc" = "yes" ; then
   if test "$GNU_MALLOC" = yes ; then
     GNU_MALLOC_reason="
@@ -1604,6 +1613,14 @@
   fi
   AC_DEFINE(DOUG_LEA_MALLOC, 1,
 	    [Define to 1 if you are using the GNU C Library.])
+
+  ## Use mmap directly for allocating larger buffers.
+  ## FIXME this comes from src/s/{gnu,gnu-linux}.h:
+  ## #ifdef DOUG_LEA_MALLOC; #undef REL_ALLOC; #endif
+  ## Does the AC_FUNC_MMAP test below make this check unecessary?
+  case "$opsys" in
+    gnu*) REL_ALLOC=no ;;
+  esac
 fi
 
 if test x"${REL_ALLOC}" = x; then
@@ -3189,26 +3206,31 @@
 	     (This is automatic if you use X, but the option to specify it remains.)
 	     It is also defined with other window systems that support xmenu.c.])
 fi
+
 if test "${GNU_MALLOC}" = "yes" ; then
   AC_DEFINE(GNU_MALLOC, 1,
 	    [Define to 1 if you want to use the GNU memory allocator.])
 fi
+
+RALLOC_OBJ=
 if test "${REL_ALLOC}" = "yes" ; then
   AC_DEFINE(REL_ALLOC, 1,
 	    [Define REL_ALLOC if you want to use the relocating allocator for
 	     buffer space.])
+
+  test "$system_malloc" != "yes" && RALLOC_OBJ=ralloc.o
 fi
-
+AC_SUBST(RALLOC_OBJ)
 
 if test "$opsys" = "cygwin"; then
   CYGWIN_OBJ="sheap.o"
   ## Cygwin differs because of its unexec().
   PRE_ALLOC_OBJ=
-  POST_ALLOC_OBJ="lastfile.o vm-limit.o"
+  POST_ALLOC_OBJ=lastfile.o
 else
   CYGWIN_OBJ=
   PRE_ALLOC_OBJ=lastfile.o
-  POST_ALLOC_OBJ="\$(vmlimitobj)"
+  POST_ALLOC_OBJ=
 fi
 AC_SUBST(CYGWIN_OBJ)
 AC_SUBST(PRE_ALLOC_OBJ)
--- a/doc/emacs/ChangeLog	Mon May 17 12:37:57 2010 +0000
+++ b/doc/emacs/ChangeLog	Tue May 18 11:35:42 2010 +0000
@@ -1,3 +1,12 @@
+2010-05-18  Eli Zaretskii  <eliz@gnu.org>
+
+	* display.texi (Fringes): Document reversal of fringe arrows for R2L
+	paragraphs.
+	(Line Truncation): Fix wording for bidi display.
+
+	* basic.texi (Moving Point): Document bidi-aware behavior of he arrow
+	keys.
+
 2010-05-08  Chong Yidong  <cyd@stupidchicken.com>
 
 	* building.texi (GDB Graphical Interface): Remove misleading comparison
--- a/doc/emacs/basic.texi	Mon May 17 12:37:57 2010 +0000
+++ b/doc/emacs/basic.texi	Tue May 18 11:35:42 2010 +0000
@@ -146,6 +146,8 @@
 @findex move-end-of-line
 @findex forward-char
 @findex backward-char
+@findex right-arrow-command
+@findex left-arrow-command
 @findex next-line
 @findex previous-line
 @findex beginning-of-buffer
@@ -161,11 +163,19 @@
 @itemx @key{End}
 Move to the end of the line (@code{move-end-of-line}).
 @item C-f
-@itemx @key{right}
 Move forward one character (@code{forward-char}).
+@item @key{right}
+Move one character to the right (@code{right-arrow-command}).  This
+moves one character forward in text that is read in the usual
+left-to-right direction, but one character @emph{backward} if the text
+is read right-to-left, as needed for right-to-left scripts such as
+Arabic.  @xref{Bidirectional Editing}.
 @item C-b
-@itemx @key{left}
 Move backward one character (@code{backward-char}).
+@item @key{left}
+Move one character to the left (@code{left-arrow-command}).  This
+moves one character backward in left-to-right text and one character
+forward in right-to-left text.
 @item M-f
 @itemx M-@key{right}
 @itemx C-@key{right}
--- a/doc/emacs/display.texi	Mon May 17 12:37:57 2010 +0000
+++ b/doc/emacs/display.texi	Tue May 18 11:35:42 2010 +0000
@@ -804,7 +804,10 @@
 screen.  The left fringe shows a curving arrow for each screen line
 except the first, indicating that ``this is not the real beginning.''
 The right fringe shows a curving arrow for each screen line except the
-last, indicating that ``this is not the real end.''
+last, indicating that ``this is not the real end.''  If the line's
+direction is right-to-left (@pxref{Bidirectional Editing}), the
+meaning of the curving arrows in the left and right fringes are
+swapped.
 
   The fringes indicate line truncation with short horizontal arrows
 meaning ``there's more text on this line which is scrolled
@@ -1191,8 +1194,8 @@
 characters that do not fit in the width of the screen or window do not
 appear at all.  On graphical displays, a small straight arrow in the
 fringe indicates truncation at either end of the line.  On text-only
-terminals, @samp{$} appears in the first column when there is text
-truncated to the left, and in the last column when there is text
+terminals, @samp{$} appears in the leftmost column when there is text
+truncated to the left, and in the rightmost column when there is text
 truncated to the right.
 
 @vindex truncate-lines
--- a/etc/NEWS	Mon May 17 12:37:57 2010 +0000
+++ b/etc/NEWS	Tue May 18 11:35:42 2010 +0000
@@ -210,6 +210,8 @@
 
 * New Modes and Packages in Emacs 24.1
 
+** smie.el is a package providing a simple generic indentation engine.
+
 ** secrets.el is an implementation of the Secret Service API, an
 interface to password managers like GNOME Keyring or KDE Wallet.  The
 Secret Service API requires D-Bus for communication.
--- a/lisp/ChangeLog	Mon May 17 12:37:57 2010 +0000
+++ b/lisp/ChangeLog	Tue May 18 11:35:42 2010 +0000
@@ -1,15 +1,31 @@
+2010-05-18  Juanma Barranquero  <lekktu@gmail.com>
+
+	* progmodes/prolog.el (smie-indent-basic): Declare for byte-compiler.
+
+	* emacs-lisp/smie.el (smie-precs-precedence-table, smie-backward-sexp)
+	(smie-forward-sexp, smie-indent-calculate): Fix typos in docstrings.
+
+2010-05-17  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	Provide a simple generic indentation engine and use it for Prolog.
+	* emacs-lisp/smie.el: New file.
+	* progmodes/prolog.el (prolog-smie-op-levels)
+	(prolog-smie-indent-rules): New var.
+	(prolog-mode-variables): Use them to configure SMIE.
+	(prolog-indent-line, prolog-indent-level): Remove.
+
 2010-05-17  Jay Belanger  <jay.p.belanger@gmail.com>
 
-	* calc/calc-vec.el (math-vector-avg):  Put the vector elements in
+	* calc/calc-vec.el (math-vector-avg): Put the vector elements in
 	order before computing the averages.
 
 2010-05-16  Jay Belanger  <jay.p.belanger@gmail.com>
 
 	* calc/calc-vec.el (calc-histogram):
-	(calcFunc-histogram):  Allow vectors as inputs.
+	(calcFunc-histogram): Allow vectors as inputs.
 	(math-vector-avg): New function.
 
-	* calc/calc-ext.el (math-group-float):  Have the number of digits
+	* calc/calc-ext.el (math-group-float): Have the number of digits
 	being grouped depend on the radix (Bug#6189).
 
 2010-05-15  Ken Raeburn  <raeburn@raeburn.org>
@@ -55,9 +71,9 @@
 	* calc/calc-units.el (calc-explain-units-rec): Allow Greek letters.
 
 	* calc/calc.el (var-π, var-φ, var-γ): New variables.
-	* calc/calc-aent.el (math-read-replacement-list):  Add "micro" symbol.
+	* calc/calc-aent.el (math-read-replacement-list): Add "micro" symbol.
 	* calc/calc-units.el (math-unit-prefixes): Add mu for micro.
-	(math-standard-units):  Add units.
+	(math-standard-units): Add units.
 
 2010-05-15  Stefan Monnier  <monnier@iro.umontreal.ca>
 
@@ -102,8 +118,7 @@
 
 2010-05-13  Chong Yidong  <cyd@stupidchicken.com>
 
-	Add TeX open-block and close-block keybindings to SGML, and vice
-	versa.
+	Add TeX open-block and close-block keybindings to SGML, and vice versa.
 
 	* textmodes/tex-mode.el (tex-mode-map): Bind C-c C-t to
 	latex-open-block and C-c / to latex-close-block.
@@ -409,7 +424,7 @@
 
 	* Version 23.2 released.
 
-2010-05-07  Deniz Dogan <deniz.a.m.dogan@gmail.com>  (tiny change)
+2010-05-07  Deniz Dogan  <deniz.a.m.dogan@gmail.com>  (tiny change)
             Stefan Monnier  <monnier@iro.umontreal.ca>
 
 	Highlight vendor specific properties.
@@ -430,7 +445,7 @@
 	* simple.el (auto-save-mode): Move from files.el.
 	* minibuffer.el (completion--common-suffix): Fix copy&paste error.
 
-2010-05-07  Christian von Roques <roques@mti.ag> (tiny change)
+2010-05-07  Christian von Roques  <roques@mti.ag>  (tiny change)
 
 	* lisp/epg.el (epg-key-capablity-alist): Add "D" flag (Bug#5592).
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/emacs-lisp/smie.el	Tue May 18 11:35:42 2010 +0000
@@ -0,0 +1,688 @@
+;;; smie.el --- Simple Minded Indentation Engine
+
+;; Copyright (C) 2010  Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Keywords: languages, lisp, internal, parsing, indentation
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; While working on the SML indentation code, the idea grew that maybe
+;; I could write something generic to do the same thing, and at the
+;; end of working on the SML code, I had a pretty good idea of what it
+;; could look like.  That idea grew stronger after working on
+;; LaTeX indentation.
+;;
+;; So at some point I decided to try it out, by writing a new
+;; indentation code for Coq while trying to keep most of the code
+;; "table driven", where only the tables are Coq-specific.  The result
+;; (which was used for Beluga-mode as well) turned out to be based on
+;; something pretty close to an operator precedence parser.
+
+;; So here is another rewrite, this time following the actual principles of
+;; operator precedence grammars.  Why OPG?  Even though they're among the
+;; weakest kinds of parsers, these parsers have some very desirable properties
+;; for Emacs:
+;; - most importantly for indentation, they work equally well in either
+;;   direction, so you can use them to parse backward from the indentation
+;;   point to learn the syntactic context;
+;; - they work locally, so there's no need to keep a cache of
+;;   the parser's state;
+;; - because of that locality, indentation also works just fine when earlier
+;;   parts of the buffer are syntactically incorrect since the indentation
+;;   looks at "as little as possible" of the buffer make an indentation
+;;   decision.
+;; - they typically have no error handling and can't even detect a parsing
+;;   error, so we don't have to worry about what to do in case of a syntax
+;;   error because the parser just automatically does something.  Better yet,
+;;   we can afford to use a sloppy grammar.
+
+;; The development (especially the parts building the 2D precedence
+;; tables and then computing the precedence levels from it) is largely
+;; inspired from page 187-194 of "Parsing techniques" by Dick Grune
+;; and Ceriel Jacobs (BookBody.pdf available at
+;; http://www.cs.vu.nl/~dick/PTAPG.html).
+;;
+;; OTOH we had to kill many chickens, read many coffee grounds, and practiced
+;; untold numbers of black magic spells.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+;;; Building precedence level tables from BNF specs.
+
+(defun smie-set-prec2tab (table x y val &optional override)
+  (assert (and x y))
+  (let* ((key (cons x y))
+         (old (gethash key table)))
+    (if (and old (not (eq old val)))
+        (if (gethash key override)
+            ;; FIXME: The override is meant to resolve ambiguities,
+            ;; but it also hides real conflicts.  It would be great to
+            ;; be able to distinguish the two cases so that overrides
+            ;; don't hide real conflicts.
+            (puthash key (gethash key override) table)
+          (display-warning 'smie (format "Conflict: %s %s/%s %s" x old val y)))
+      (puthash key val table))))
+
+(defun smie-precs-precedence-table (precs)
+  "Compute a 2D precedence table from a list of precedences.
+PRECS should be a list, sorted by precedence (e.g. \"+\" will
+come before \"*\"), of elements of the form \(left OP ...)
+or (right OP ...) or (nonassoc OP ...)  or (assoc OP ...).  All operators in
+one of those elements share the same precedence level and associativity."
+  (let ((prec2-table (make-hash-table :test 'equal)))
+    (dolist (prec precs)
+      (dolist (op (cdr prec))
+        (let ((selfrule (cdr (assq (car prec)
+                                   '((left . >) (right . <) (assoc . =))))))
+          (when selfrule
+            (dolist (other-op (cdr prec))
+              (smie-set-prec2tab prec2-table op other-op selfrule))))
+        (let ((op1 '<) (op2 '>))
+          (dolist (other-prec precs)
+            (if (eq prec other-prec)
+                (setq op1 '> op2 '<)
+              (dolist (other-op (cdr other-prec))
+                (smie-set-prec2tab prec2-table op other-op op2)
+                (smie-set-prec2tab prec2-table other-op op op1)))))))
+    prec2-table))
+
+(defun smie-merge-prec2s (tables)
+  (if (null (cdr tables))
+      (car tables)
+    (let ((prec2 (make-hash-table :test 'equal)))
+      (dolist (table tables)
+        (maphash (lambda (k v)
+                   (smie-set-prec2tab prec2 (car k) (cdr k) v))
+                 table))
+      prec2)))
+
+(defun smie-bnf-precedence-table (bnf &rest precs)
+  (let ((nts (mapcar 'car bnf))         ;Non-terminals
+        (first-ops-table ())
+        (last-ops-table ())
+        (first-nts-table ())
+        (last-nts-table ())
+        (prec2 (make-hash-table :test 'equal))
+        (override (smie-merge-prec2s
+                   (mapcar 'smie-precs-precedence-table precs)))
+        again)
+    (dolist (rules bnf)
+      (let ((nt (car rules))
+            (last-ops ())
+            (first-ops ())
+            (last-nts ())
+            (first-nts ()))
+        (dolist (rhs (cdr rules))
+          (assert (consp rhs))
+          (if (not (member (car rhs) nts))
+              (pushnew (car rhs) first-ops)
+            (pushnew (car rhs) first-nts)
+            (when (consp (cdr rhs))
+              ;; If the first is not an OP we add the second (which
+              ;; should be an OP if BNF is an "operator grammar").
+              ;; Strictly speaking, this should only be done if the
+              ;; first is a non-terminal which can expand to a phrase
+              ;; without any OP in it, but checking doesn't seem worth
+              ;; the trouble, and it lets the writer of the BNF
+              ;; be a bit more sloppy by skipping uninteresting base
+              ;; cases which are terminals but not OPs.
+              (assert (not (member (cadr rhs) nts)))
+              (pushnew (cadr rhs) first-ops)))
+          (let ((shr (reverse rhs)))
+            (if (not (member (car shr) nts))
+                (pushnew (car shr) last-ops)
+              (pushnew (car shr) last-nts)
+            (when (consp (cdr shr))
+              (assert (not (member (cadr shr) nts)))
+              (pushnew (cadr shr) last-ops)))))
+        (push (cons nt first-ops) first-ops-table)
+        (push (cons nt last-ops) last-ops-table)
+        (push (cons nt first-nts) first-nts-table)
+        (push (cons nt last-nts) last-nts-table)))
+    ;; Compute all first-ops by propagating the initial ones we have
+    ;; now, according to first-nts.
+    (setq again t)
+    (while (prog1 again (setq again nil))
+      (dolist (first-nts first-nts-table)
+        (let* ((nt (pop first-nts))
+               (first-ops (assoc nt first-ops-table)))
+          (dolist (first-nt first-nts)
+            (dolist (op (cdr (assoc first-nt first-ops-table)))
+              (unless (member op first-ops)
+                (setq again t)
+                (push op (cdr first-ops))))))))
+    ;; Same thing for last-ops.
+    (setq again t)
+    (while (prog1 again (setq again nil))
+      (dolist (last-nts last-nts-table)
+        (let* ((nt (pop last-nts))
+               (last-ops (assoc nt last-ops-table)))
+          (dolist (last-nt last-nts)
+            (dolist (op (cdr (assoc last-nt last-ops-table)))
+              (unless (member op last-ops)
+                (setq again t)
+                (push op (cdr last-ops))))))))
+    ;; Now generate the 2D precedence table.
+    (dolist (rules bnf)
+      (dolist (rhs (cdr rules))
+        (while (cdr rhs)
+          (cond
+           ((member (car rhs) nts)
+            (dolist (last (cdr (assoc (car rhs) last-ops-table)))
+              (smie-set-prec2tab prec2 last (cadr rhs) '> override)))
+           ((member (cadr rhs) nts)
+            (dolist (first (cdr (assoc (cadr rhs) first-ops-table)))
+              (smie-set-prec2tab prec2 (car rhs) first '< override))
+            (if (and (cddr rhs) (not (member (car (cddr rhs)) nts)))
+                (smie-set-prec2tab prec2 (car rhs) (car (cddr rhs))
+                                   '= override)))
+           (t (smie-set-prec2tab prec2 (car rhs) (cadr rhs) '= override)))
+          (setq rhs (cdr rhs)))))
+    prec2))
+
+(defun smie-prec2-levels (prec2)
+  "Take a 2D precedence table and turn it into an alist of precedence levels.
+PREC2 is a table as returned by `smie-precs-precedence-table' or
+`smie-bnf-precedence-table'."
+  ;; For each operator, we create two "variables" (corresponding to
+  ;; the left and right precedence level), which are represented by
+  ;; cons cells.  Those are the vary cons cells that appear in the
+  ;; final `table'.  The value of each "variable" is kept in the `car'.
+  (let ((table ())
+        (csts ())
+        (eqs ())
+        tmp x y)
+    ;; From `prec2' we construct a list of constraints between
+    ;; variables (aka "precedence levels").  These can be either
+    ;; equality constraints (in `eqs') or `<' constraints (in `csts').
+    (maphash (lambda (k v)
+               (if (setq tmp (assoc (car k) table))
+                   (setq x (cddr tmp))
+                 (setq x (cons nil nil))
+                 (push (cons (car k) (cons nil x)) table))
+               (if (setq tmp (assoc (cdr k) table))
+                   (setq y (cdr tmp))
+                 (setq y (cons nil (cons nil nil)))
+                 (push (cons (cdr k) y) table))
+               (ecase v
+                 (= (push (cons x y) eqs))
+                 (< (push (cons x y) csts))
+                 (> (push (cons y x) csts))))
+             prec2)
+    ;; First process the equality constraints.
+    (let ((eqs eqs))
+      (while eqs
+        (let ((from (caar eqs))
+              (to (cdar eqs)))
+          (setq eqs (cdr eqs))
+          (if (eq to from)
+              (debug)                   ;Can it happen?
+            (dolist (other-eq eqs)
+              (if (eq from (cdr other-eq)) (setcdr other-eq to))
+              (when (eq from (car other-eq))
+                ;; This can happen because of `assoc' settings in precs
+                ;; or because of a rhs like ("op" foo "op").
+                (setcar other-eq to)))
+            (dolist (cst csts)
+              (if (eq from (cdr cst)) (setcdr cst to))
+              (if (eq from (car cst)) (setcar cst to)))))))
+    ;; Then eliminate trivial constraints iteratively.
+    (let ((i 0))
+      (while csts
+        (let ((rhvs (mapcar 'cdr csts))
+              (progress nil))
+          (dolist (cst csts)
+            (unless (memq (car cst) rhvs)
+              (setq progress t)
+              (setcar (car cst) i)
+              (setq csts (delq cst csts))))
+          (unless progress
+            (error "Can't resolve the precedence table to precedence levels")))
+        (incf i))
+      ;; Propagate equalities back to their source.
+      (dolist (eq (nreverse eqs))
+        (assert (null (caar eq)))
+        (setcar (car eq) (cadr eq)))
+      ;; Finally, fill in the remaining vars (which only appeared on the
+      ;; right side of the < constraints).
+      ;; Tho leaving them at nil is not a bad choice, since it makes
+      ;; it clear that these don't bind at all.
+      ;; (dolist (x table)
+      ;;   (unless (nth 1 x) (setf (nth 1 x) i))
+      ;;   (unless (nth 2 x) (setf (nth 2 x) i)))
+      )
+    table))
+
+;;; Parsing using a precedence level table.
+
+(defvar smie-op-levels 'unset
+  "List of token parsing info.
+Each element is of the form (TOKEN LEFT-LEVEL RIGHT-LEVEL).
+Parsing is done using an operator precedence parser.")
+
+(defun smie-backward-token ()
+  ;; FIXME: This may be an OK default but probably needs a hook.
+  (buffer-substring (point)
+                    (progn (if (zerop (skip-syntax-backward "."))
+                               (skip-syntax-backward "w_'"))
+                           (point))))
+
+(defun smie-forward-token ()
+  ;; FIXME: This may be an OK default but probably needs a hook.
+  (buffer-substring (point)
+                    (progn (if (zerop (skip-syntax-forward "."))
+                               (skip-syntax-forward "w_'"))
+                           (point))))
+
+(defun smie-backward-sexp (&optional halfsexp)
+  "Skip over one sexp.
+HALFSEXP if non-nil, means skip over a partial sexp if needed.  I.e. if the
+first token we see is an operator, skip over its left-hand-side argument.
+Possible return values:
+  (LEFT-LEVEL POS TOKEN): we couldn't skip TOKEN because its right-level
+    is too high.  LEFT-LEVEL is the left-level of TOKEN,
+    POS is its start position in the buffer.
+  (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
+  (nil POS TOKEN): we skipped over a paren-like pair.
+  nil: we skipped over an identifier, matched parentheses, ..."
+  (if (bobp) (list t (point))
+    (catch 'return
+      (let ((levels ()))
+        (while
+            (let* ((pos (point))
+                   (token (progn (forward-comment (- (point-max)))
+                                 (smie-backward-token)))
+                   (toklevels (cdr (assoc token smie-op-levels))))
+
+              (cond
+               ((null toklevels)
+                (if (equal token "")
+                    (condition-case err
+                        (progn (goto-char pos) (backward-sexp 1) nil)
+                      (scan-error (throw 'return (list t (caddr err)))))))
+               ((null (nth 1 toklevels))
+                ;; A token like a paren-close.
+                (assert (nth 0 toklevels)) ;Otherwise, why mention it?
+                (push (nth 0 toklevels) levels))
+               (t
+                (while (and levels (< (nth 1 toklevels) (car levels)))
+                  (setq levels (cdr levels)))
+                (cond
+                 ((null levels)
+                  (if (and halfsexp (nth 0 toklevels))
+                      (push (nth 0 toklevels) levels)
+                    (throw 'return
+                           (prog1 (list (or (car toklevels) t) (point) token)
+                             (goto-char pos)))))
+                 (t
+                  (while (and levels (= (nth 1 toklevels) (car levels)))
+                    (setq levels (cdr levels)))
+                  (cond
+                   ((null levels)
+                    (cond
+                     ((null (nth 0 toklevels))
+                      (throw 'return (list nil (point) token)))
+                     ((eq (nth 0 toklevels) (nth 1 toklevels))
+                      (throw 'return
+                             (prog1 (list (or (car toklevels) t) (point) token)
+                               (goto-char pos))))
+                     (t (debug))))      ;Not sure yet what to do here.
+                   (t
+                    (if (nth 0 toklevels)
+                        (push (nth 0 toklevels) levels))))))))
+              levels)
+          (setq halfsexp nil))))))
+
+;; Mirror image, not used for indentation.
+(defun smie-forward-sexp (&optional halfsexp)
+  "Skip over one sexp.
+HALFSEXP if non-nil, means skip over a partial sexp if needed.  I.e. if the
+first token we see is an operator, skip over its left-hand-side argument.
+Possible return values:
+  (RIGHT-LEVEL POS TOKEN): we couldn't skip TOKEN because its left-level
+    is too high.  RIGHT-LEVEL is the right-level of TOKEN,
+    POS is its end position in the buffer.
+  (t POS TOKEN): same thing but for an open-paren or the beginning of buffer.
+  (nil POS TOKEN): we skipped over a paren-like pair.
+  nil: we skipped over an identifier, matched parentheses, ..."
+  (if (eobp) (list t (point))
+    (catch 'return
+      (let ((levels ()))
+        (while
+            (let* ((pos (point))
+                   (token (progn (forward-comment (point-max))
+                                 (smie-forward-token)))
+                   (toklevels (cdr (assoc token smie-op-levels))))
+
+              (cond
+               ((null toklevels)
+                (if (equal token "")
+                    (condition-case err
+                        (progn (goto-char pos) (forward-sexp 1) nil)
+                      (scan-error (throw 'return (list t (caddr err)))))))
+               ((null (nth 0 toklevels))
+                ;; A token like a paren-close.
+                (assert (nth 1 toklevels)) ;Otherwise, why mention it?
+                (push (nth 1 toklevels) levels))
+               (t
+                (while (and levels (< (nth 0 toklevels) (car levels)))
+                  (setq levels (cdr levels)))
+                (cond
+                 ((null levels)
+                  (if (and halfsexp (nth 1 toklevels))
+                      (push (nth 1 toklevels) levels)
+                    (throw 'return
+                           (prog1 (list (or (nth 1 toklevels) t) (point) token)
+                             (goto-char pos)))))
+                 (t
+                  (while (and levels (= (nth 0 toklevels) (car levels)))
+                    (setq levels (cdr levels)))
+                  (cond
+                   ((null levels)
+                    (cond
+                     ((null (nth 1 toklevels))
+                      (throw 'return (list nil (point) token)))
+                     ((eq (nth 1 toklevels) (nth 0 toklevels))
+                      (throw 'return
+                             (prog1 (list (or (nth 1 toklevels) t) (point) token)
+                               (goto-char pos))))
+                     (t (debug))))      ;Not sure yet what to do here.
+                   (t
+                    (if (nth 1 toklevels)
+                        (push (nth 1 toklevels) levels))))))))
+              levels)
+          (setq halfsexp nil))))))
+
+(defun smie-backward-sexp-command (&optional n)
+  "Move backward through N logical elements."
+  (interactive "p")
+  (if (< n 0)
+      (smie-forward-sexp-command (- n))
+    (let ((forward-sexp-function nil))
+      (while (> n 0)
+        (decf n)
+        (let ((pos (point))
+              (res (smie-backward-sexp 'halfsexp)))
+          (if (and (car res) (= pos (point)) (not (bolp)))
+              (signal 'scan-error
+                      (list "Containing expression ends prematurely"
+                            (cadr res) (cadr res)))
+            nil))))))
+
+(defun smie-forward-sexp-command (&optional n)
+  "Move forward through N logical elements."
+  (interactive "p")
+  (if (< n 0)
+      (smie-backward-sexp-command (- n))
+    (let ((forward-sexp-function nil))
+      (while (> n 0)
+        (decf n)
+        (let ((pos (point))
+              (res (smie-forward-sexp 'halfsexp)))
+          (if (and (car res) (= pos (point)) (not (bolp)))
+              (signal 'scan-error
+                      (list "Containing expression ends prematurely"
+                            (cadr res) (cadr res)))
+            nil))))))
+
+;;; The indentation engine.
+
+(defcustom smie-indent-basic 4
+  "Basic amount of indentation."
+  :type 'integer)
+
+(defvar smie-indent-rules 'unset
+  "Rules of the following form.
+\(TOK OFFSET)		how to indent right after TOK.
+\(TOK O1 O2)		how to indent right after TOK:
+			  O1 is the default;
+			  O2 is used if TOK is \"hanging\".
+\((T1 . T2) . OFFSET)	how to indent token T2 w.r.t T1.
+\((t . TOK) . OFFSET)	how to indent TOK with respect to its parent.
+\(list-intro . TOKENS)	declare TOKENS as being followed by what may look like
+			  a funcall but is just a sequence of expressions.
+\(t . OFFSET)		basic indentation step.
+\(args . OFFSET)		indentation of arguments.
+A nil offset defaults to `smie-indent-basic'.")
+
+(defun smie-indent-hanging-p ()
+  ;; A Hanging keyword is one that's at the end of a line except it's not at
+  ;; the beginning of a line.
+  (and (save-excursion (smie-forward-token)
+                       (skip-chars-forward " \t") (eolp))
+       (save-excursion (skip-chars-backward " \t") (not (bolp)))))
+
+(defun smie-bolp ()
+  (save-excursion (skip-chars-backward " \t") (bolp)))
+
+(defun smie-indent-offset (elem)
+  (or (cdr (assq elem smie-indent-rules))
+      (cdr (assq t smie-indent-rules))
+      smie-indent-basic))
+
+(defun smie-indent-calculate (&optional virtual)
+  "Compute the indentation to use for point.
+If VIRTUAL is non-nil, it means we're not trying to indent point but just
+need to compute the column at which point should be indented
+in order to figure out the indentation of some other (further down) point.
+VIRTUAL can take two different non-nil values:
+- :bolp: means that the current indentation of point can be trusted
+  to be good only if it follows a line break.
+- :hanging: means that the current indentation of point can be
+  trusted to be good except if the following token is hanging."
+  ;; FIXME: This has accumulated a lot of rules, some of which aren't
+  ;; clearly orthogonal any more, so we should probably try and
+  ;; restructure it somewhat.
+  (or
+   ;; Trust pre-existing indentation on other lines.
+   (and virtual
+        (if (eq virtual :hanging) (not (smie-indent-hanging-p)) (smie-bolp))
+        (current-column))
+   ;; Align close paren with opening paren.
+   (save-excursion
+     ;; (forward-comment (point-max))
+     (when (looking-at "\\s)")
+       (while (not (zerop (skip-syntax-forward ")")))
+         (skip-chars-forward " \t"))
+       (condition-case nil
+           (progn
+             (backward-sexp 1)
+             (smie-indent-calculate :hanging))
+         (scan-error nil))))
+   ;; Align closing token with the corresponding opening one.
+   ;; (e.g. "of" with "case", or "in" with "let").
+   (save-excursion
+     (let* ((pos (point))
+            (token (smie-forward-token))
+            (toklevels (cdr (assoc token smie-op-levels))))
+       (when (car toklevels)
+         (let ((res (smie-backward-sexp 'halfsexp)) tmp)
+           ;; If we didn't move at all, that means we didn't really skip
+           ;; what we wanted.
+           (when (< (point) pos)
+             (cond
+              ((eq (car res) (car toklevels))
+               ;; We bumped into a same-level operator. align with it.
+               (goto-char (cadr res))
+               ;; Don't use (smie-indent-calculate :hanging) here, because we
+               ;; want to jump back over a sequence of same-level ops such as
+               ;;    a -> b -> c
+               ;;    -> d
+               ;; So as to align with the earliest appropriate place.
+               (smie-indent-calculate :bolp))
+              ((equal token (save-excursion
+                              (forward-comment (- (point-max)))
+                              (smie-backward-token)))
+               ;; in cases such as "fn x => fn y => fn z =>",
+               ;; jump back to the very first fn.
+               ;; FIXME: should we only do that for special tokens like "=>"?
+               (smie-indent-calculate :bolp))
+              ((setq tmp (assoc (cons (caddr res) token)
+                                smie-indent-rules))
+               (goto-char (cadr res))
+               (+ (cdr tmp) (smie-indent-calculate :hanging)))
+              (t
+               (+ (or (cdr (assoc (cons t token) smie-indent-rules)) 0)
+                  (current-column)))))))))
+   ;; Indentation of a comment.
+   (and (looking-at comment-start-skip)
+        (save-excursion
+          (forward-comment (point-max))
+          (skip-chars-forward " \t\r\n")
+          (smie-indent-calculate nil)))
+   ;; Indentation inside a comment.
+   (and (looking-at "\\*") (nth 4 (syntax-ppss))
+        (let ((ppss (syntax-ppss)))
+          (save-excursion
+            (forward-line -1)
+            (if (<= (point) (nth 8 ppss))
+                (progn (goto-char (1+ (nth 8 ppss))) (current-column))
+              (skip-chars-forward " \t")
+              (if (looking-at "\\*")
+                  (current-column))))))
+   ;; Indentation right after a special keyword.
+   (save-excursion
+     (let* ((tok (progn (forward-comment (- (point-max)))
+                        (smie-backward-token)))
+            (tokinfo (assoc tok smie-indent-rules))
+            (toklevel (assoc tok smie-op-levels)))
+       (when (or tokinfo (and toklevel (null (cadr toklevel))))
+         (if (or (smie-indent-hanging-p)
+                 ;; If calculating the virtual indentation point, prefer
+                 ;; looking up the virtual indentation of the alignment
+                 ;; point as well.  This is used for indentation after
+                 ;; "fn x => fn y =>".
+                 virtual)
+             (+ (smie-indent-calculate :bolp)
+                (or (caddr tokinfo) (cadr tokinfo) (smie-indent-offset t)))
+           (+ (current-column)
+              (or (cadr tokinfo) (smie-indent-offset t)))))))
+   ;; Main loop (FIXME: whatever that means!?).
+   (save-excursion
+     (let ((positions nil)
+           (begline nil)
+           arg)
+       (while (and (null (car (smie-backward-sexp)))
+                   (push (point) positions)
+                   (not (setq begline (smie-bolp)))))
+       (save-excursion
+         ;; Figure out if the atom we just skipped is an argument rather
+         ;; than a function.
+         (setq arg (or (null (car (smie-backward-sexp)))
+                       (member (progn (forward-comment (- (point-max)))
+                                      (smie-backward-token))
+                               (cdr (assoc 'list-intro smie-indent-rules))))))
+       (cond
+        ((and arg positions)
+         (goto-char (car positions))
+         (current-column))
+        ((and (null begline) (cdr positions))
+         ;; We skipped some args plus the function and bumped into something.
+         ;; Align with the first arg.
+         (goto-char (cadr positions))
+         (current-column))
+        ((and (null begline) positions)
+         ;; We're the first arg.
+         ;; FIXME: it might not be a funcall, in which case we might be the
+         ;; second element.
+         (goto-char (car positions))
+         (+ (smie-indent-offset 'args)
+            ;; We used to use (smie-indent-calculate :bolp), but that
+            ;; doesn't seem right since it might then indent args less than
+            ;; the function itself.
+            (current-column)))
+        ((and (null arg) (null positions))
+         ;; We're the function itself.  Not sure what to do here yet.
+         (if virtual (current-column)
+           (save-excursion
+             (let* ((pos (point))
+                    (tok (progn (forward-comment (- (point-max)))
+                                (smie-backward-token)))
+                    (toklevels (cdr (assoc tok smie-op-levels))))
+               (cond
+                ((numberp (car toklevels))
+                 ;; We're right after an infix token.  Let's skip over the
+                 ;; lefthand side.
+                 (goto-char pos)
+                 (let (res)
+                   (while (progn (setq res (smie-backward-sexp 'halfsexp))
+                                 (and (not (smie-bolp))
+                                      (equal (car res) (car toklevels)))))
+                   ;; We should be right after a token of equal or
+                   ;; higher precedence.
+                   (cond
+                    ((and (consp res) (memq (car res) '(t nil)))
+                     ;; The token of higher-precedence is like an open-paren.
+                     ;; Sample case for t: foo { bar, \n[TAB] baz }.
+                     ;; Sample case for nil: match ... with \n[TAB] | toto ...
+                     ;; (goto-char (cadr res))
+                     (smie-indent-calculate :hanging))
+                    ((and (consp res) (<= (car res) (car toklevels)))
+                     ;; We stopped at a token of equal or higher precedence
+                     ;; because we found a place with which to align.
+                     (current-column))
+                    )))
+                ;; For other cases.... hmm... we'll see when we get there.
+                )))))
+        ((null positions)
+         (smie-backward-token)
+         (+ (smie-indent-offset 'args) (smie-indent-calculate :bolp)))
+        ((car (smie-backward-sexp))
+         ;; No arg stands on its own line, but the function does:
+         (if (cdr positions)
+             (progn
+               (goto-char (cadr positions))
+               (current-column))
+           (goto-char (car positions))
+           (+ (current-column) (smie-indent-offset 'args))))
+        (t
+         ;; We've skipped to a previous arg on its own line: align.
+         (goto-char (car positions))
+         (current-column)))))))
+
+(defun smie-indent-line ()
+  "Indent current line using the SMIE indentation engine."
+  (interactive)
+  (let* ((savep (point))
+	 (indent (condition-case nil
+		     (save-excursion
+                       (forward-line 0)
+                       (skip-chars-forward " \t")
+                       (if (>= (point) savep) (setq savep nil))
+                       (or (smie-indent-calculate) 0))
+                   (error 0))))
+    (if (not (numberp indent))
+        ;; If something funny is used (e.g. `noindent'), return it.
+        indent
+      (if (< indent 0) (setq indent 0)) ;Just in case.
+      (if savep
+          (save-excursion (indent-line-to indent))
+        (indent-line-to indent)))))
+
+;;;###autoload
+(defun smie-setup (op-levels indent-rules)
+  (set (make-local-variable 'smie-indent-rules) indent-rules)
+  (set (make-local-variable 'smie-op-levels) op-levels)
+  (set (make-local-variable 'indent-line-function) 'smie-indent-line))
+
+
+(provide 'smie)
+;;; smie.el ends here
--- a/lisp/progmodes/prolog.el	Mon May 17 12:37:57 2010 +0000
+++ b/lisp/progmodes/prolog.el	Tue May 18 11:35:42 2010 +0000
@@ -31,6 +31,7 @@
 
 (defvar comint-prompt-regexp)
 (defvar comint-process-echoes)
+(defvar smie-indent-basic)
 
 (defgroup prolog nil
   "Major mode for editing and running Prolog under Emacs."
@@ -98,6 +99,61 @@
 (defvar prolog-mode-abbrev-table nil)
 (define-abbrev-table 'prolog-mode-abbrev-table ())
 
+(defconst prolog-smie-op-levels
+  ;; Rather than construct the operator levels table from the BNF,
+  ;; we directly provide the operator precedences from GNU Prolog's
+  ;; manual.  The only problem is that GNU Prolog's manual uses
+  ;; precedence levels in the opposite sense (higher numbers bind less
+  ;; tightly) than SMIE, so we use negative numbers.
+  '(("." -10000 -10000)
+    (":-" -1200 -1200)
+    ("-->" -1200 -1200)
+    (";" -1100 -1100)
+    ("->" -1050 -1050)
+    ("," -1000 -1000)
+    ("\\+" -900 -900)
+    ("=" -700 -700)
+    ("\\=" -700 -700)
+    ("=.." -700 -700)
+    ("==" -700 -700)
+    ("\\==" -700 -700)
+    ("@<" -700 -700)
+    ("@=<" -700 -700)
+    ("@>" -700 -700)
+    ("@>=" -700 -700)
+    ("is" -700 -700)
+    ("=:=" -700 -700)
+    ("=\\=" -700 -700)
+    ("<" -700 -700)
+    ("=<" -700 -700)
+    (">" -700 -700)
+    (">=" -700 -700)
+    (":" -600 -600)
+    ("+" -500 -500)
+    ("-" -500 -500)
+    ("/\\" -500 -500)
+    ("\\/" -500 -500)
+    ("*" -400 -400)
+    ("/" -400 -400)
+    ("//" -400 -400)
+    ("rem" -400 -400)
+    ("mod" -400 -400)
+    ("<<" -400 -400)
+    (">>" -400 -400)
+    ("**" -200 -200)
+    ("^" -200 -200)
+    ;; Prefix
+    ;; ("+" 200 200)
+    ;; ("-" 200 200)
+    ;; ("\\" 200 200)
+    )
+  "Precedence levels of infix operators.")
+
+(defconst prolog-smie-indent-rules
+  '((":-")
+    ("->"))
+  "Prolog indentation rules.")
+
 (defun prolog-mode-variables ()
   (make-local-variable 'paragraph-separate)
   (setq paragraph-separate (concat "%%\\|$\\|" page-delimiter)) ;'%%..'
@@ -105,8 +161,10 @@
   (setq paragraph-ignore-fill-prefix t)
   (make-local-variable 'imenu-generic-expression)
   (setq imenu-generic-expression '((nil "^\\sw+" 0)))
-  (make-local-variable 'indent-line-function)
-  (setq indent-line-function 'prolog-indent-line)
+  (smie-setup prolog-smie-op-levels prolog-smie-indent-rules)
+  (set (make-local-variable 'forward-sexp-function)
+       'smie-forward-sexp-command)
+  (set (make-local-variable 'smie-indent-basic) prolog-indent-width)
   (make-local-variable 'comment-start)
   (setq comment-start "%")
   (make-local-variable 'comment-start-skip)
@@ -122,7 +180,7 @@
     (define-key map "\C-c\C-l" 'inferior-prolog-load-file)
     (define-key map "\C-c\C-z" 'switch-to-prolog)
     map))
- 
+
 (easy-menu-define prolog-mode-menu prolog-mode-map "Menu for Prolog mode."
   ;; Mostly copied from scheme-mode's menu.
   ;; Not tremendously useful, but it's a start.
@@ -149,65 +207,6 @@
                              nil nil nil
                              beginning-of-line)))
 
-(defun prolog-indent-line ()
-  "Indent current line as Prolog code.
-With argument, indent any additional lines of the same clause
-rigidly along with this one (not yet)."
-  (interactive "p")
-  (let ((indent (prolog-indent-level))
-	(pos (- (point-max) (point))))
-    (beginning-of-line)
-    (indent-line-to indent)
-    (if (> (- (point-max) pos) (point))
-	(goto-char (- (point-max) pos)))))
-
-(defun prolog-indent-level ()
-  "Compute Prolog indentation level."
-  (save-excursion
-    (beginning-of-line)
-    (skip-chars-forward " \t")
-    (cond
-     ((looking-at "%%%") 0)		;Large comment starts
-     ((looking-at "%[^%]") comment-column) ;Small comment starts
-     ((bobp) 0)				;Beginning of buffer
-     (t
-      (let ((empty t) ind more less)
-	(if (looking-at ")")
-	    (setq less t)		;Find close
-	  (setq less nil))
-	;; See previous indentation
-	(while empty
-	  (forward-line -1)
-	  (beginning-of-line)
- 	  (if (bobp)
- 	      (setq empty nil)
- 	    (skip-chars-forward " \t")
- 	    (if (not (or (looking-at "%[^%]") (looking-at "\n")))
- 		(setq empty nil))))
- 	(if (bobp)
- 	    (setq ind 0)		;Beginning of buffer
-	  (setq ind (current-column)))	;Beginning of clause
-	;; See its beginning
-	(if (looking-at "%%[^%]")
-	    ind
-	  ;; Real prolog code
-	  (if (looking-at "(")
-	      (setq more t)		;Find open
-	    (setq more nil))
-	  ;; See its tail
-	  (end-of-prolog-clause)
-	  (or (bobp) (forward-char -1))
-	  (cond ((looking-at "[,(;>]")
-		 (if (and more (looking-at "[^,]"))
-		     (+ ind prolog-indent-width) ;More indentation
-		   (max tab-width ind))) ;Same indentation
-		((looking-at "-") tab-width) ;TAB
-		((or less (looking-at "[^.]"))
-		 (max (- ind prolog-indent-width) 0)) ;Less indentation
-		(t 0))			;No indentation
-	  )))
-     )))
-
 (defun end-of-prolog-clause ()
   "Go to end of clause in this line."
   (beginning-of-line 1)
--- a/lisp/simple.el	Mon May 17 12:37:57 2010 +0000
+++ b/lisp/simple.el	Tue May 18 11:35:42 2010 +0000
@@ -2077,7 +2077,11 @@
 
 Like `shell-command' but if COMMAND doesn't end in ampersand, adds `&'
 surrounded by whitespace and executes the command asynchronously.
-The output appears in the buffer `*Async Shell Command*'."
+The output appears in the buffer `*Async Shell Command*'.
+
+In Elisp, you will often be better served by calling `start-process'
+directly, since it offers more control and does not impose the use of a
+shell (with its need to quote arguments)."
   (interactive
    (list
     (read-shell-command "Async shell command: " nil nil
@@ -2138,7 +2142,11 @@
 or buffer name to which to direct the command's standard error output.
 If it is nil, error output is mingled with regular output.
 In an interactive call, the variable `shell-command-default-error-buffer'
-specifies the value of ERROR-BUFFER."
+specifies the value of ERROR-BUFFER.
+
+In Elisp, you will often be better served by calling `call-process' or
+`start-process' directly, since it offers more control and does not impose
+the use of a shell (with its need to quote arguments)."
 
   (interactive
    (list
--- a/msdos/ChangeLog	Mon May 17 12:37:57 2010 +0000
+++ b/msdos/ChangeLog	Tue May 18 11:35:42 2010 +0000
@@ -1,3 +1,14 @@
+2010-05-18  Eli Zaretskii  <eliz@gnu.org>
+
+	* sed1x.inp: Add copyright notice.
+
+2010-05-18  Glenn Morris  <rgm@gnu.org>
+
+	* sed1v2.inp (RALLOC_OBJ): Edit to ralloc.o.
+
+	* sed1v2.inp (GMALLOC_OBJ): Edit to gmalloc.o.
+	(VMLIMIT_OBJ): Edit to vm-limit.o.
+
 2010-05-17  Glenn Morris  <rgm@gnu.org>
 
 	* sed1v2.inp (OLDXMENU_DEPS): Edit to empty.
--- a/msdos/sed1v2.inp	Mon May 17 12:37:57 2010 +0000
+++ b/msdos/sed1v2.inp	Tue May 18 11:35:42 2010 +0000
@@ -116,6 +116,9 @@
 /^OLDXMENU *=/s/@OLDXMENU@//
 /^LIBXMENU *=/s/@LIBXMENU@//
 /^LIBX_OTHER *=/s/@LIBX_OTHER@//
+/^GMALLOC_OBJ *=/s/@GMALLOC_OBJ@/gmalloc.o/
+/^VMLIMIT_OBJ *=/s/@VMLIMIT_OBJ@/vm-limit.o/
+/^RALLOC_OBJ *=/s/@RALLOC_OBJ@/ralloc.o/
 /^PRE_ALLOC_OBJ *=/s/@PRE_ALLOC_OBJ@/lastfile.o/
 /^POST_ALLOC_OBJ *=/s/@POST_ALLOC_OBJ@/$(vmlimitobj)/
 /^UNEXEC_OBJ *=/s/@unexec@/unexec.o/
--- a/msdos/sed1x.inp	Mon May 17 12:37:57 2010 +0000
+++ b/msdos/sed1x.inp	Tue May 18 11:35:42 2010 +0000
@@ -1,6 +1,21 @@
 # -sed1x.inp------------------------------------------------------------
 # Extra configuration script for src/makefile for DesqView/X
 # ----------------------------------------------------------------------
+#
+# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
+#   2005, 2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# This file is free software; as a special exception, the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# 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.
+#
+# ----------------------------------------------------------------------
 s!^	cd \${oldXMenudir}; \${MAKE}.*$!	${MAKE} -C ${oldXMenudir}.!
 s!^	@true *$!	@rem!
 s/DOC/DOC-X/g
--- a/src/ChangeLog	Mon May 17 12:37:57 2010 +0000
+++ b/src/ChangeLog	Tue May 18 11:35:42 2010 +0000
@@ -1,3 +1,25 @@
+2010-05-18  Juanma Barranquero  <lekktu@gmail.com>
+
+	* charset.c (load_charset_map_from_file): Don't call close after fclose.
+
+2010-05-18  Glenn Morris  <rgm@gnu.org>
+
+	* s/gnu-linux.h: Combine two conditionals.
+
+	* Makefile.in (otherobj): Include $(VMLIMIT_OBJ) separately from
+	$(POST_ALLOC_OBJ).
+
+	* Makefile.in (RALLOC_OBJ): New, set by configure.
+	(rallocobj): Replace with the previous variable.
+	(otherobj): Use $RALLOC_OBJ.
+
+	* s/gnu.h (REL_ALLOC) [DOUG_LEA_MALLOC]:
+	* s/gnu-linux.h (REL_ALLOC) [DOUG_LEA_MALLOC]: Move undef to configure.
+
+	* Makefile.in (GMALLOC_OBJ, VMLIMIT_OBJ): New, set by configure.
+	(gmallocobj, vmlimitobj): Replace with previous two variables.
+	(otherobj): Use $GMALLOC_OBJ, $VMLIMIT_OBJ.
+
 2010-05-17  Glenn Morris  <rgm@gnu.org>
 
 	* Makefile.in (OLDXMENU_DEPS): New, set by configure.
@@ -45,8 +67,7 @@
 
 2010-05-15  Ken Raeburn  <raeburn@raeburn.org>
 
-	* lisp.h (XFLOAT_DATA): Use "0?x:x" to generate an
-	rvalue. (bug#5916)
+	* lisp.h (XFLOAT_DATA): Use "0?x:x" to generate an rvalue.  (Bug#5916)
 	(LISP_MAKE_RVALUE) [!USE_LISP_UNION_TYPE && !__GNUC__]: Likewise.
 
 	* emacs.c (main): Initialize initial-environment and
@@ -120,8 +141,7 @@
 
 2010-05-14  Kenichi Handa  <handa@m17n.org>
 
-	* font.c (font_range): Return the range for the font found at
-	first.
+	* font.c (font_range): Return the range for the font found at first.
 
 2010-05-14  Glenn Morris  <rgm@gnu.org>
 
@@ -11580,7 +11600,7 @@
 	definitions from xmenu.c.  Suggested by Adrian Robert.
 
 	* xmenu.c: Remove platform-independent menu definitions.
-	(menu_items menu_items_inuse, menu_items_allocated)
+	(menu_items, menu_items_inuse, menu_items_allocated)
 	(menu_items_used, menu_items_n_panes)
 	(menu_items_submenu_depth): Move to keyboard.h.
 	(init_menu_items, finish_menu_items, unuse_menu_items)
--- a/src/Makefile.in	Mon May 17 12:37:57 2010 +0000
+++ b/src/Makefile.in	Tue May 18 11:35:42 2010 +0000
@@ -401,29 +401,23 @@
   w32.o w32console.o w32fns.o w32heap.o w32inevt.o \
   w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o $(FONT_OBJ)
 
-gmallocobj =
-rallocobj =
-vmlimitobj =
-#ifndef SYSTEM_MALLOC
-#ifndef DOUG_LEA_MALLOC
-gmallocobj = gmalloc.o
-#endif
+/* gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.  */
+GMALLOC_OBJ=@GMALLOC_OBJ@
 
-#ifdef REL_ALLOC
-rallocobj = ralloc.o
-#endif
+/* vm-limit.o if !SYSTEM_MALLOC, else empty.  */
+VMLIMIT_OBJ=@VMLIMIT_OBJ@
 
-vmlimitobj = vm-limit.o
-#endif /* !SYSTEM_MALLOC */
+/* ralloc.o if !SYSTEM_MALLOC && REL_ALLOC, else empty.  */
+RALLOC_OBJ=@RALLOC_OBJ@
 
 /* Empty on Cygwin, lastfile.o elsewhere.  */
 PRE_ALLOC_OBJ=@PRE_ALLOC_OBJ@
-/* lastfile.o vm-limit.o on Cygwin, $vmlimitobj elsewhere.  */
+/* lastfile.o on Cygwin, empty elsewhere.  */
 POST_ALLOC_OBJ=@POST_ALLOC_OBJ@
 
 /* List of object files that make-docfile should not be told about.  */
-otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(gmallocobj) $(rallocobj) \
-  $(POST_ALLOC_OBJ) $(WIDGET_OBJ) $(LIBOBJS)
+otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
+  $(POST_ALLOC_OBJ) $(VMLIMIT_OBJ) $(WIDGET_OBJ) $(LIBOBJS)
 
 /* This is the platform-specific list of Lisp files loaded into the
    dumped Emacs.  It is arranged like this because it is easier to generate
@@ -1098,7 +1092,9 @@
 /* Since the .el.elc rule cannot specify an extra dependency, we do it here.  */
 ${lisp} ${SOME_MACHINE_LISP}: $(BOOTSTRAPEMACS)
 
-${lispsource}loaddefs.el: $(BOOTSTRAPEMACS)
+/* VCSWITNESS points to the file that holds info about the current checkout.
+   We use it as a heuristic to decide when to rebuild loaddefs.el.  */
+${lispsource}loaddefs.el: $(BOOTSTRAPEMACS) $(VCSWITNESS)
 	cd ../lisp; $(MAKE) $(MFLAGS) autoloads EMACS=${bootstrap_exe}
 
 /* Dump an Emacs executable named bootstrap-emacs containing the
--- a/src/charset.c	Mon May 17 12:37:57 2010 +0000
+++ b/src/charset.c	Tue May 18 11:35:42 2010 +0000
@@ -567,7 +567,6 @@
       n_entries++;
     }
   fclose (fp);
-  close (fd);
 
   load_charset_map (charset, head, n_entries, control_flag);
   SAFE_FREE ();
--- a/src/m/template.h	Mon May 17 12:37:57 2010 +0000
+++ b/src/m/template.h	Tue May 18 11:35:42 2010 +0000
@@ -69,11 +69,14 @@
    reasonable place to select for it is in the machine description file.  */
 #define NO_SOCK_SIGIO
 
-/* After adding support for a new system, modify the large case
-   statement in the `configure' script to recognize reasonable
+/* After adding support for a new machine, modify the large case
+   statement in configure.in to recognize reasonable
    configuration names, and add a description of the system to
    `etc/MACHINES'.
 
+   Check for any tests of $machine in configure.in, and add an entry
+   for the new machine if needed.
+
    If you've just fixed a problem in an existing configuration file,
    you should also check `etc/MACHINES' to make sure its descriptions
    of known problems in that configuration should be updated.  */
--- a/src/s/gnu-linux.h	Mon May 17 12:37:57 2010 +0000
+++ b/src/s/gnu-linux.h	Tue May 18 11:35:42 2010 +0000
@@ -97,7 +97,6 @@
 /* This is used in list_system_processes.  */
 #define HAVE_PROCFS 1
 
-
 /* Define CLASH_DETECTION if you want lock files to be written
    so that Emacs can tell instantly when you try to modify
    a file that someone else has modified in his Emacs.  */
@@ -126,12 +125,10 @@
 #define GNU_LIBRARY_PENDING_OUTPUT_COUNT(FILE) \
   ((FILE)->_pptr - (FILE)->_pbase)
 #endif /* !_IO_STDIO_H && ! __UCLIBC__ */
+
+#define INTERRUPT_INPUT
 #endif /* emacs */
 
-#ifdef emacs
-#define INTERRUPT_INPUT
-#endif
-
 #define SYSV_SYSTEM_DIR       /* use dirent.h */
 
 #define POSIX                 /* affects getpagesize.h and systty.h */
@@ -147,11 +144,6 @@
 
 #define NARROWPROTO 1
 
-/* Use mmap directly for allocating larger buffers.  */
-#ifdef DOUG_LEA_MALLOC
-#undef REL_ALLOC
-#endif
-
 /* Tell that garbage collector that setjmp is known to save all
    registers relevant for conservative garbage collection in the jmp_buf.  */
 /* Not all the architectures are tested, but there are Debian packages
--- a/src/s/gnu.h	Mon May 17 12:37:57 2010 +0000
+++ b/src/s/gnu.h	Tue May 18 11:35:42 2010 +0000
@@ -1,6 +1,7 @@
 /* Definitions file for GNU Emacs running on the GNU Hurd.
-   Copyright (C) 1994, 1995, 1996, 2001, 2002, 2003, 2004, 2005, 2006,
-                 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+
+Copyright (C) 1994, 1995, 1996, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+  2008, 2009, 2010  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -28,11 +29,6 @@
 
 #define SIGNALS_VIA_CHARACTERS
 
-/* Use mmap directly for allocating larger buffers.  */
-#ifdef DOUG_LEA_MALLOC
-#undef REL_ALLOC
-#endif
-
 /* GNU needs its own crt0, and libc defines data_start.  */
 #define ORDINARY_LINK
 #define DATA_START ({ extern int data_start; (char *) &data_start; })
--- a/src/s/template.h	Mon May 17 12:37:57 2010 +0000
+++ b/src/s/template.h	Tue May 18 11:35:42 2010 +0000
@@ -133,10 +133,13 @@
 /* ============================================================ */
 
 /* After adding support for a new system, modify the large case
-   statement in the `configure' script to recognize reasonable
+   statement in configure.in to recognize reasonable
    configuration names, and add a description of the system to
    `etc/MACHINES'.
 
+   Check for any tests of $opsys in configure.in, and add an entry
+   for the new system if needed.
+
    If you've just fixed a problem in an existing configuration file,
    you should also check `etc/MACHINES' to make sure its descriptions
    of known problems in that configuration should be updated.  */