emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/native-comp 3608623 9/9: Merge remote-tracking branch 'savannah/


From: Andrea Corallo
Subject: feature/native-comp 3608623 9/9: Merge remote-tracking branch 'savannah/master' into HEAD
Date: Sun, 5 Apr 2020 17:25:08 -0400 (EDT)

branch: feature/native-comp
commit 3608623eba9870aff8b5eb842fb8ae10f092c6bb
Merge: 4263f2f 95a7c6e
Author: Andrea Corallo <address@hidden>
Commit: Andrea Corallo <address@hidden>

    Merge remote-tracking branch 'savannah/master' into HEAD
---
 etc/NEWS                    |   6 +
 lib-src/Makefile.in         |   2 -
 lisp/arc-mode.el            | 973 +++++++++++++++++++++-----------------------
 lisp/faces.el               |   2 +-
 lisp/progmodes/cc-engine.el |  13 +-
 lisp/progmodes/gdb-mi.el    |  11 +-
 src/Makefile.in             |   7 +-
 src/character.c             |  39 +-
 src/lisp.h                  |  22 +-
 9 files changed, 521 insertions(+), 554 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index fa33364..81a70e9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -101,6 +101,12 @@ horizontal movements now stop at the edge of the board.
 
 * Changes in Specialized Modes and Packages in Emacs 28.1
 
+** archive-mode
+*** Can now modify members of 'ar' archives.
+*** Display of summaries unified between backends
+*** New var 'archive-hidden-columns' and cmd 'archive-hideshow-column'
+These let you control which columns are displayed and which are kept hidden
+
 ** Emacs-Lisp mode
 
 *** The mode-line now indicates whether we're using lexical or dynamic scoping.
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 29b34d9..a2d27ea 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -231,8 +231,6 @@ BASE_CFLAGS = $(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) \
              -I${srcdir} -I${srcdir}/../src -I${srcdir}/../lib
 
 ALL_CFLAGS = ${BASE_CFLAGS} ${PROFILING_CFLAGS} ${LDFLAGS} ${CPPFLAGS} 
${CFLAGS}
-## Unused.
-LINK_CFLAGS = ${BASE_CFLAGS} ${LDFLAGS} ${CFLAGS}
 CPP_CFLAGS = ${BASE_CFLAGS} ${PROFILING_CFLAGS} ${CPPFLAGS} ${CFLAGS}
 
 # Configuration files for .o files to depend on.
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 677483e..4d36667 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -1,4 +1,4 @@
-;;; arc-mode.el --- simple editing of archives
+;;; arc-mode.el --- simple editing of archives  -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1995, 1997-1998, 2001-2020 Free Software Foundation,
 ;; Inc.
@@ -52,17 +52,17 @@
 ;; ARCHIVE TYPES: Currently only the archives below are handled, but the
 ;; structure for handling just about anything is in place.
 ;;
-;;                     Arc     Lzh     Zip     Zoo     Rar     7z
-;;                     --------------------------------------------
-;; View listing                Intern  Intern  Intern  Intern  Y       Y
-;; Extract member      Y       Y       Y       Y       Y       Y
-;; Save changed member Y       Y       Y       Y       N       Y
-;; Add new member      N       N       N       N       N       N
-;; Delete member       Y       Y       Y       Y       N       Y
-;; Rename member       Y       Y       N       N       N       N
-;; Chmod               -       Y       Y       -       N       N
-;; Chown               -       Y       -       -       N       N
-;; Chgrp               -       Y       -       -       N       N
+;;                     Arc     Lzh     Zip     Zoo     Rar     7z      Ar
+;;                     --------------------------------------------------
+;; View listing                Intern  Intern  Intern  Intern  Y       Y       
Y
+;; Extract member      Y       Y       Y       Y       Y       Y       Y
+;; Save changed member Y       Y       Y       Y       N       Y       Y
+;; Add new member      N       N       N       N       N       N       N
+;; Delete member       Y       Y       Y       Y       N       Y       N
+;; Rename member       Y       Y       N       N       N       N       N
+;; Chmod               -       Y       Y       -       N       N       N
+;; Chown               -       Y       -       -       N       N       N
+;; Chgrp               -       Y       -       -       N       N       N
 ;;
 ;; Special thanks to Bill Brodie <address@hidden> for very useful tips
 ;; on the first released version of this package.
@@ -101,6 +101,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl-lib))
+
 ;; -------------------------------------------------------------------------
 ;;; Section: Configuration.
 
@@ -108,22 +110,6 @@
   "Simple editing of archives."
   :group 'data)
 
-(defgroup archive-arc nil
-  "ARC-specific options to archive."
-  :group 'archive)
-
-(defgroup archive-lzh nil
-  "LZH-specific options to archive."
-  :group 'archive)
-
-(defgroup archive-zip nil
-  "ZIP-specific options to archive."
-  :group 'archive)
-
-(defgroup archive-zoo nil
-  "ZOO-specific options to archive."
-  :group 'archive)
-
 (defcustom archive-tmpdir
   ;; make-temp-name is safe here because we use this name
   ;; to create a directory.
@@ -131,35 +117,48 @@
    (expand-file-name (if (eq system-type 'ms-dos) "ar" "archive.tmp")
                     temporary-file-directory))
   "Directory for temporary files made by `arc-mode.el'."
-  :type 'directory
-  :group 'archive)
+  :type 'directory)
 
 (defcustom archive-remote-regexp "^/[^/:]*[^/:.]:"
   "Regexp recognizing archive files names that are not local.
 A non-local file is one whose file name is not proper outside Emacs.
 A local copy of the archive will be used when updating."
-  :type 'regexp
-  :group 'archive)
+  :type 'regexp)
 
 (define-obsolete-variable-alias 'archive-extract-hooks
   'archive-extract-hook "24.3")
 (defcustom archive-extract-hook nil
   "Hook run when an archive member has been extracted."
-  :type 'hook
-  :group 'archive)
+  :type 'hook)
 
 (defcustom archive-visit-single-files nil
   "If non-nil, opening an archive with a single file visits that file.
 If nil, visiting such an archive displays the archive summary."
   :version "25.1"
   :type '(choice (const :tag "Visit the single file" t)
-                 (const :tag "Show the archive summary" nil))
-  :group 'archive)
+                 (const :tag "Show the archive summary" nil)))
+
+(defcustom archive-hidden-columns '(Ids)
+  "Columns hidden from display."
+  :version "28.1"
+  :type '(set (const Mode)
+              (const Ids)
+              (const Date&Time)
+              (const Ratio)))
+
+(defconst archive-alternate-hidden-columns '(Mode Date&Time)
+  "Columns hidden when `archive-alternate-display' is used.")
+
 ;; ------------------------------
 ;; Arc archive configuration
 
 ;; We always go via a local file since there seems to be no reliable way
 ;; to extract to stdout without junk getting added.
+
+(defgroup archive-arc nil
+  "ARC-specific options to archive."
+  :group 'archive)
+
 (defcustom archive-arc-extract
   '("arc" "x")
   "Program and its options to run in order to extract an arc file member.
@@ -168,8 +167,7 @@ name will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-arc)
+                       (string :format "%v"))))
 
 (defcustom archive-arc-expunge
   '("arc" "d")
@@ -178,8 +176,7 @@ Archive and member names will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-arc)
+                       (string :format "%v"))))
 
 (defcustom archive-arc-write-file-member
   '("arc" "u")
@@ -188,11 +185,14 @@ Archive and member name will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-arc)
+                       (string :format "%v"))))
 ;; ------------------------------
 ;; Lzh archive configuration
 
+(defgroup archive-lzh nil
+  "LZH-specific options to archive."
+  :group 'archive)
+
 (defcustom archive-lzh-extract
   '("lha" "pq")
   "Program and its options to run in order to extract an lzh file member.
@@ -201,8 +201,7 @@ be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-lzh)
+                       (string :format "%v"))))
 
 (defcustom archive-lzh-expunge
   '("lha" "d")
@@ -211,8 +210,7 @@ Archive and member names will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-lzh)
+                       (string :format "%v"))))
 
 (defcustom archive-lzh-write-file-member
   '("lha" "a")
@@ -221,8 +219,7 @@ Archive and member name will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-lzh)
+                       (string :format "%v"))))
 ;; ------------------------------
 ;; Zip archive configuration
 
@@ -231,6 +228,10 @@ Archive and member name will be added."
                              (when 7z
                                (file-name-nondirectory 7z))))
 
+(defgroup archive-zip nil
+  "ZIP-specific options to archive."
+  :group 'archive)
+
 (defcustom archive-zip-extract
   (cond ((executable-find "unzip")   '("unzip" "-qq" "-c"))
        (archive-7z-program          `(,archive-7z-program "x" "-so"))
@@ -242,8 +243,7 @@ be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-zip)
+                      (string :format "%v"))))
 
 ;; For several reasons the latter behavior is not desirable in general.
 ;; (1) It uses more disk space.  (2) Error checking is worse or non-
@@ -260,8 +260,7 @@ Archive and member names will be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-zip)
+                      (string :format "%v"))))
 
 (defcustom archive-zip-update
   (cond ((executable-find "zip")     '("zip" "-q"))
@@ -274,8 +273,7 @@ file.  Archive and member name will be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-zip)
+                      (string :format "%v"))))
 
 (defcustom archive-zip-update-case
   (cond ((executable-find "zip")     '("zip" "-q" "-k"))
@@ -288,8 +286,7 @@ Archive and member name will be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-zip)
+                      (string :format "%v"))))
 
 (declare-function msdos-long-file-names "msdos.c")
 (defcustom archive-zip-case-fiddle (and (eq system-type 'ms-dos)
@@ -300,11 +297,14 @@ that uses caseless file names.
 In addition, this flag forces members added/updated in the zip archive
 to be truncated to DOS 8+3 file-name restrictions."
   :type 'boolean
-  :version "27.1"
-  :group 'archive-zip)
+  :version "27.1")
 ;; ------------------------------
 ;; Zoo archive configuration
 
+(defgroup archive-zoo nil
+  "ZOO-specific options to archive."
+  :group 'archive)
+
 (defcustom archive-zoo-extract
   '("zoo" "xpq")
   "Program and its options to run in order to extract a zoo file member.
@@ -313,8 +313,7 @@ be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-zoo)
+                       (string :format "%v"))))
 
 (defcustom archive-zoo-expunge
   '("zoo" "DqPP")
@@ -323,8 +322,7 @@ Archive and member names will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-zoo)
+                       (string :format "%v"))))
 
 (defcustom archive-zoo-write-file-member
   '("zoo" "a")
@@ -333,11 +331,14 @@ Archive and member name will be added."
   :type '(list (string :tag "Program")
                (repeat :tag "Options"
                        :inline t
-                       (string :format "%v")))
-  :group 'archive-zoo)
+                       (string :format "%v"))))
 ;; ------------------------------
 ;; 7z archive configuration
 
+(defgroup archive-7z nil
+  "7Z-specific options to archive."
+  :group 'archive)
+
 (defcustom archive-7z-extract
   `(,(or archive-7z-program "7z") "x" "-so")
   "Program and its options to run in order to extract a 7z file member.
@@ -347,8 +348,7 @@ be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-7z)
+                      (string :format "%v"))))
 
 (defcustom archive-7z-expunge
   `(,(or archive-7z-program "7z") "d")
@@ -358,8 +358,7 @@ Archive and member names will be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-7z)
+                      (string :format "%v"))))
 
 (defcustom archive-7z-update
   `(,(or archive-7z-program "7z") "u")
@@ -370,18 +369,17 @@ file.  Archive and member name will be added."
   :type '(list (string :tag "Program")
               (repeat :tag "Options"
                       :inline t
-                      (string :format "%v")))
-  :group 'archive-7z)
+                      (string :format "%v"))))
 
 ;; -------------------------------------------------------------------------
 ;;; Section: Variables
 
 (defvar archive-subtype nil "Symbol describing archive type.")
-(defvar archive-file-list-start nil "Position of first contents line.")
-(defvar archive-file-list-end nil "Position just after last contents line.")
-(defvar archive-proper-file-start nil "Position of real archive's start.")
+(defvar-local archive-file-list-start nil "Position of first contents line.")
+(defvar-local archive-file-list-end nil "Position just after last contents 
line.")
+(defvar-local archive-proper-file-start nil "Position of real archive's 
start.")
 (defvar archive-read-only nil "Non-nil if the archive is read-only on disk.")
-(defvar archive-local-name nil "Name of local copy of remote archive.")
+(defvar-local archive-local-name nil "Name of local copy of remote archive.")
 (defvar archive-mode-map
   (let ((map (make-keymap)))
     (set-keymap-parent map special-mode-map)
@@ -428,7 +426,6 @@ file.  Archive and member name will be added."
       (cons "Immediate" (make-sparse-keymap "Immediate")))
     (define-key map [menu-bar immediate alternate]
       '(menu-item "Alternate Display" archive-alternate-display
-                  :enable (boundp (archive-name "alternate-display"))
                   :help "Toggle alternate file info display"))
     (define-key map [menu-bar immediate view]
       '(menu-item "View This File" archive-view
@@ -483,36 +480,58 @@ file.  Archive and member name will be added."
                   :help "Delete all flagged files from archive"))
     map)
   "Local keymap for archive mode listings.")
-(defvar archive-file-name-indent nil "Column where file names start.")
+(defvar-local archive-file-name-indent nil "Column where file names start.")
 
-(defvar archive-remote nil "Non-nil if the archive is outside file system.")
-(make-variable-buffer-local 'archive-remote)
+(defvar-local archive-remote nil "Non-nil if the archive is outside file 
system.")
 (put 'archive-remote 'permanent-local t)
 
-(defvar archive-member-coding-system nil "Coding-system of archive member.")
-(make-variable-buffer-local 'archive-member-coding-system)
+(defvar-local archive-member-coding-system nil "Coding-system of archive 
member.")
 
-(defvar archive-alternate-display nil
+(defvar-local archive-alternate-display nil
   "Non-nil when alternate information is shown.")
-(make-variable-buffer-local 'archive-alternate-display)
 (put 'archive-alternate-display 'permanent-local t)
 
 (defvar archive-superior-buffer nil "In archive members, points to archive.")
 (put 'archive-superior-buffer 'permanent-local t)
 
-(defvar archive-subfile-mode nil "Non-nil in archive member buffers.")
-(make-variable-buffer-local 'archive-subfile-mode)
+(defvar-local archive-subfile-mode nil
+  "Non-nil in archive member buffers.
+Its value is an `archive--file-desc'.")
 (put 'archive-subfile-mode 'permanent-local t)
 
-(defvar archive-file-name-coding-system nil)
-(make-variable-buffer-local 'archive-file-name-coding-system)
+(defvar-local archive-file-name-coding-system nil)
 (put 'archive-file-name-coding-system 'permanent-local t)
 
-(defvar archive-files nil
-  "Vector of file descriptors.
-Each descriptor is a vector of the form
- [EXT-FILE-NAME INT-FILE-NAME CASE-FIDDLED MODE ...]")
-(make-variable-buffer-local 'archive-files)
+(cl-defstruct (archive--file-desc
+               (:constructor nil)
+               (:constructor archive--file-desc
+                ;; ext-file-name and int-file-name are usually `eq'
+                ;; except when int-file-name is the downcased
+                ;; ext-file-name.
+                (ext-file-name int-file-name mode size time
+                               &key pos ratio uid gid)))
+  ext-file-name int-file-name
+  (mode nil  :type integer)
+  (size nil  :type integer)
+  (time nil  :type string)
+  (ratio nil :type string)
+  uid gid
+  pos)
+
+;; Features in formats:
+;;
+;; ARC: size, date&time (date and time strings internally generated)
+;; LZH: size, date&time, mode, uid, gid (mode, date, time generated, ugid:int)
+;; ZIP: size, date&time, mode (mode, date, time generated)
+;; ZOO: size, date&time (date and time strings internally generated)
+;; AR : size, date&time, mode, user, group (internally generated)
+;; RAR: size, date&time, ratio (all as strings, using `lsar')
+;; 7Z : size, date&time (all as strings, using `7z' or `7za')
+;;
+;; LZH has alternate display (with UID/GID i.s.o MODE/DATE/TIME
+
+(defvar-local archive-files nil
+  "Vector of `archive--file-desc' objects.")
 
 ;; -------------------------------------------------------------------------
 ;;; Section: Support functions.
@@ -520,9 +539,9 @@ Each descriptor is a vector of the form
 (defun arc-insert-unibyte (&rest args)
   "Like insert but don't make unibyte string and eight-bit char multibyte."
   (dolist (elt args)
-    (if (integerp elt)
-       (insert (if (< elt 128) elt (decode-char 'eight-bit elt)))
-      (insert elt))))
+    (insert (if (and (integerp elt) (>= elt 128))
+                (decode-char 'eight-bit elt)
+              elt))))
 
 (defsubst archive-name (suffix)
   (intern (concat "archive-" (symbol-name archive-subtype) "-" suffix)))
@@ -547,70 +566,36 @@ in which case a second argument, length LEN, should be 
supplied."
 (defun archive-int-to-mode (mode)
   "Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------."
   ;; FIXME: merge with tar-grind-file-mode.
-  (string
-    (if (zerop (logand  8192 mode))
-       (if (zerop (logand 16384 mode)) ?- ?d)
-      ?c) ; completeness
-    (if (zerop (logand   256 mode)) ?- ?r)
-    (if (zerop (logand   128 mode)) ?- ?w)
-    (if (zerop (logand    64 mode))
-       (if (zerop (logand  2048 mode)) ?- ?S)
-      (if (zerop (logand  2048 mode)) ?x ?s))
-    (if (zerop (logand    32 mode)) ?- ?r)
-    (if (zerop (logand    16 mode)) ?- ?w)
-    (if (zerop (logand     8 mode))
-       (if (zerop (logand  1024 mode)) ?- ?S)
-      (if (zerop (logand  1024 mode)) ?x ?s))
-    (if (zerop (logand     4 mode)) ?- ?r)
-    (if (zerop (logand     2 mode)) ?- ?w)
-    (if (zerop (logand     1 mode)) ?- ?x)))
-
-(defun archive-calc-mode (oldmode newmode &optional error)
+  (if (null mode)
+      "??????????"
+    (string
+     (if (zerop (logand  8192 mode))
+        (if (zerop (logand 16384 mode)) ?- ?d)
+       ?c)                              ; completeness
+     (if (zerop (logand   256 mode)) ?- ?r)
+     (if (zerop (logand   128 mode)) ?- ?w)
+     (if (zerop (logand    64 mode))
+        (if (zerop (logand  2048 mode)) ?- ?S)
+       (if (zerop (logand  2048 mode)) ?x ?s))
+     (if (zerop (logand    32 mode)) ?- ?r)
+     (if (zerop (logand    16 mode)) ?- ?w)
+     (if (zerop (logand     8 mode))
+        (if (zerop (logand  1024 mode)) ?- ?S)
+       (if (zerop (logand  1024 mode)) ?x ?s))
+     (if (zerop (logand     4 mode)) ?- ?r)
+     (if (zerop (logand     2 mode)) ?- ?w)
+     (if (zerop (logand     1 mode)) ?- ?x))))
+
+(defun archive-calc-mode (oldmode newmode)
   "From the integer OLDMODE and the string NEWMODE calculate a new file mode.
 NEWMODE may be an octal number including a leading zero in which case it
 will become the new mode.\n
 NEWMODE may also be a relative specification like \"og-rwx\" in which case
-OLDMODE will be modified accordingly just like chmod(2) would have done.\n
-If optional third argument ERROR is non-nil an error will be signaled if
-the mode is invalid.  If ERROR is nil then nil will be returned."
-  (cond ((string-match "^0[0-7]*$" newmode)
-        (let ((result 0)
-              (len (length newmode))
-              (i 1))
-          (while (< i len)
-            (setq result (+ (ash result 3) (aref newmode i) (- ?0))
-                  i (1+ i)))
-          (logior (logand oldmode 65024) result)))
-       ((string-match "^\\([agou]+\\)\\([---+=]\\)\\([rwxst]+\\)$" newmode)
-        (let ((who 0)
-              (result oldmode)
-              (op (aref newmode (match-beginning 2)))
-              (bits 0)
-              (i (match-beginning 3)))
-          (while (< i (match-end 3))
-            (let ((rwx (aref newmode i)))
-              (setq bits (logior bits (cond ((= rwx ?r)  292)
-                                            ((= rwx ?w)  146)
-                                            ((= rwx ?x)   73)
-                                            ((= rwx ?s) 3072)
-                                            ((= rwx ?t)  512)))
-                    i (1+ i))))
-          (while (< who (match-end 1))
-            (let* ((whoc (aref newmode who))
-                   (whomask (cond ((= whoc ?a) 4095)
-                                  ((= whoc ?u) 1472)
-                                  ((= whoc ?g) 2104)
-                                  ((= whoc ?o)    7))))
-              (if (= op ?=)
-                  (setq result (logand result (lognot whomask))))
-              (if (= op ?-)
-                  (setq result (logand result (lognot (logand whomask bits))))
-                (setq result (logior result (logand whomask bits)))))
-            (setq who (1+ who)))
-          result))
-       (t
-        (if error
-            (error "Invalid mode specification: %s" newmode)))))
+OLDMODE will be modified accordingly just like chmod(2) would have done."
+  ;; FIXME: Use `file-modes-symbolic-to-number'!
+  (if (string-match "\\`0[0-7]*\\'" newmode)
+      (logior (logand oldmode #o177000) (string-to-number newmode 8))
+    (file-modes-symbolic-to-number newmode oldmode)))
 
 (defun archive-dosdate (date)
   "Stringify dos packed DATE record."
@@ -622,7 +607,8 @@ the mode is invalid.  If ERROR is nil then nil will be 
returned."
       (format "%2d-%s-%d"
               day
               (aref ["Jan" "Feb" "Mar" "Apr" "May" "Jun"
-                     "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"] (1- month))
+                     "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"]
+                    (1- month))
               year))))
 
 (defun archive-dostime (time)
@@ -658,10 +644,12 @@ Does not signal an error if optional argument NOERROR is 
non-nil."
     (if (and (>= (point) archive-file-list-start)
              (< no (length archive-files)))
        (let ((item (aref archive-files no)))
-         (if (vectorp item)
+         (if (and (archive--file-desc-p item)
+                  (let ((mode (archive--file-desc-mode item)))
+                    (zerop (logand 16384 mode))))
              item
            (if (not noerror)
-               (error "Entry is not a regular member of the archive"))))
+               (user-error "Entry is not a regular member of the archive"))))
       (if (not noerror)
           (error "Line does not describe a member of the archive")))))
 ;; -------------------------------------------------------------------------
@@ -684,41 +672,34 @@ archive.
   ;; mode on and off.  You can corrupt things that way.
   (if (zerop (buffer-size))
       ;; At present we cannot create archives from scratch
-      (funcall (or (default-value 'major-mode) 'fundamental-mode))
+      (funcall (or (default-value 'major-mode) #'fundamental-mode))
     (if (and (not force) archive-files) nil
       (kill-all-local-variables)
       (let* ((type (archive-find-type))
             (typename (capitalize (symbol-name type))))
-       (make-local-variable 'archive-subtype)
-       (setq archive-subtype type)
+       (setq-local archive-subtype type)
 
        ;; Buffer contains treated image of file before the file contents
-       (make-local-variable 'revert-buffer-function)
-       (setq revert-buffer-function 'archive-mode-revert)
-       (auto-save-mode 0)
+       (add-function :around (local 'revert-buffer-function)
+                     #'archive--mode-revert)
 
-       (add-hook 'write-contents-functions 'archive-write-file nil t)
+       (add-hook 'write-contents-functions #'archive-write-file nil t)
 
-       (make-local-variable 'require-final-newline)
-       (setq require-final-newline nil)
-       (make-local-variable 'local-enable-local-variables)
-       (setq local-enable-local-variables nil)
+        (setq-local truncate-lines t)
+       (setq-local require-final-newline nil)
+       (setq-local local-enable-local-variables nil)
 
        ;; Prevent loss of data when saving the file.
-       (make-local-variable 'file-precious-flag)
-       (setq file-precious-flag t)
+       (setq-local file-precious-flag t)
 
-       (make-local-variable 'archive-read-only)
        ;; Archives which are inside other archives and whose
        ;; names are invalid for this OS, can't be written.
-       (setq archive-read-only
-             (or (not (file-writable-p (buffer-file-name)))
-                 (and archive-subfile-mode
-                      (string-match file-name-invalid-regexp
-                                    (aref archive-subfile-mode 0)))))
-
-       ;; Should we use a local copy when accessing from outside Emacs?
-       (make-local-variable 'archive-local-name)
+       (setq-local archive-read-only
+                   (or (not (file-writable-p (buffer-file-name)))
+                       (and archive-subfile-mode
+                            (string-match file-name-invalid-regexp
+                                          (archive--file-desc-ext-file-name
+                                           archive-subfile-mode)))))
 
        ;; An archive can contain another archive whose name is invalid
        ;; on local filesystem.  Treat such archives as remote.
@@ -728,16 +709,12 @@ archive.
                      (string-match file-name-invalid-regexp
                                    (buffer-file-name)))))
 
-       (setq major-mode 'archive-mode)
+       (setq major-mode #'archive-mode)
        (setq mode-name (concat typename "-Archive"))
        ;; Run archive-foo-mode-hook and archive-mode-hook
        (run-mode-hooks (archive-name "mode-hook") 'archive-mode-hook)
        (use-local-map archive-mode-map))
 
-      (make-local-variable 'archive-proper-file-start)
-      (make-local-variable 'archive-file-list-start)
-      (make-local-variable 'archive-file-list-end)
-      (make-local-variable 'archive-file-name-indent)
       (setq archive-file-name-coding-system
            (or file-name-coding-system
                default-file-name-coding-system
@@ -803,7 +780,7 @@ when parsing the archive."
   (let ((create-lockfiles nil) ; avoid changing dir mtime by lock_file
        (inhibit-read-only t))
     (setq archive-proper-file-start (copy-marker (point-min) t))
-    (set (make-local-variable 'change-major-mode-hook) 'archive-desummarize)
+    (add-hook 'change-major-mode-hook #'archive-desummarize nil t)
     (or shut-up
        (message "Parsing archive file..."))
     (buffer-disable-undo (current-buffer))
@@ -825,27 +802,35 @@ when parsing the archive."
     (goto-char archive-file-list-start)
     (archive-next-line no)))
 
+(cl-defstruct (archive--file-summary
+               (:constructor nil)
+               (:constructor archive--file-summary (text name-start name-end)))
+  text name-start name-end)
+
 (defun archive-summarize-files (files)
   "Insert a description of a list of files annotated with proper mouse face."
   (setq archive-file-list-start (point-marker))
-  (setq archive-file-name-indent (if files (aref (car files) 1) 0))
+  ;; Here we assume that they all start at the same column.
+  (setq archive-file-name-indent
+        ;; FIXME: We assume chars=columns (no double-wide chars and such).
+        (if files (archive--file-summary-name-start (car files)) 0))
   ;; We don't want to do an insert for each element since that takes too
   ;; long when the archive -- which has to be moved in memory -- is large.
   (insert
-   (apply
-    #'concat
-    (mapcar
-     (lambda (fil)
-       ;; Using `concat' here copies the text also, so we can add
-       ;; properties without problems.
-       (let ((text (concat (aref fil 0) "\n")))
-         (add-text-properties
-          (aref fil 1) (aref fil 2)
-          '(mouse-face highlight
-                       help-echo "mouse-2: extract this file into a buffer")
-          text)
-         text))
-     files)))
+   (mapconcat
+    (lambda (fil)
+      ;; Using `concat' here copies the text also, so we can add
+      ;; properties without problems.
+      (let ((text (concat (archive--file-summary-text fil) "\n")))
+        (add-text-properties
+         (archive--file-summary-name-start fil)
+         (archive--file-summary-name-end fil)
+         '(mouse-face highlight
+           help-echo "mouse-2: extract this file into a buffer")
+         text)
+        text))
+    files
+    ""))
   (setq archive-file-list-end (point-marker)))
 
 (defun archive-alternate-display ()
@@ -854,7 +839,27 @@ To avoid very long lines archive mode does not show all 
information.
 This function changes the set of information shown for each files."
   (interactive)
   (setq archive-alternate-display (not archive-alternate-display))
+  (setq-local archive-hidden-columns
+              (if archive-alternate-display
+                  archive-alternate-hidden-columns
+                (eval (car (or (get 'archive-hidden-columns 'customized-value)
+                               (get 'archive-hidden-columns 'standard-value)))
+                      t)))
+  (archive-resummarize))
+
+(defun archive-hideshow-column (column)
+  "Toggle visibility of COLUMN."
+  (interactive
+   (list (intern
+          (completing-read "Toggle visibility of: "
+                           '(Mode Ids Ratio Date&Time)
+                           nil t))))
+  (setq-local archive-hidden-columns
+              (if (memq column archive-hidden-columns)
+                  (remove column archive-hidden-columns)
+                (cons column archive-hidden-columns)))
   (archive-resummarize))
+
 ;; -------------------------------------------------------------------------
 ;;; Section: Local archive copy handling
 
@@ -899,7 +904,8 @@ using `make-temp-file', and the generated name is returned."
              ;; "foo.zip:bar.zip", which is invalid on DOS/Windows.
              ;; So use the actual name if available.
              (archive-name
-              (or (and archive-subfile-mode (aref archive-subfile-mode 0))
+              (or (and archive-subfile-mode (archive--file-desc-ext-file-name
+                                             archive-subfile-mode))
                   archive)))
          (setq archive-local-name
                (archive-unique-fname archive-name archive-tmpdir))
@@ -918,6 +924,7 @@ using `make-temp-file', and the generated name is returned."
            (lno (archive-get-lineno))
            (inhibit-read-only t))
        (if unchanged nil
+         ;; FIXME: Use archive-resummarize?
          (setq archive-files nil)
          (erase-buffer)
          (insert-file-contents name)
@@ -968,7 +975,7 @@ using `make-temp-file', and the generated name is returned."
         (delete-file tmpfile)))))
 
 (defun archive-file-name-handler (op &rest args)
-  (or (eq op 'file-exists-p)
+  (or (eq op #'file-exists-p)
       (let ((file-name-handler-alist nil))
        (apply op args))))
 
@@ -1008,8 +1015,8 @@ using `make-temp-file', and the generated name is 
returned."
   (if event (posn-set-point (event-end event)))
   (let* ((view-p (eq other-window-p 'view))
         (descr (archive-get-descr))
-         (ename (aref descr 0))
-         (iname (aref descr 1))
+         (ename (archive--file-desc-ext-file-name descr))
+         (iname (archive--file-desc-int-file-name descr))
          (archive-buffer (current-buffer))
          (arcdir default-directory)
          (archive (buffer-file-name))
@@ -1038,8 +1045,7 @@ using `make-temp-file', and the generated name is 
returned."
                 (abbreviate-file-name buffer-file-name))
           ;; Set the default-directory to the dir of the superior buffer.
           (setq default-directory arcdir)
-          (make-local-variable 'archive-superior-buffer)
-          (setq archive-superior-buffer archive-buffer)
+          (setq-local archive-superior-buffer archive-buffer)
           (add-hook 'write-file-functions #'archive-write-file-member nil t)
           (setq archive-subfile-mode descr)
          (setq archive-file-name-coding-system file-name-coding)
@@ -1253,7 +1259,7 @@ using `make-temp-file', and the generated name is 
returned."
   t)
 
 (defun archive-*-write-file-member (archive descr command)
-  (let* ((ename (aref descr 0))
+  (let* ((ename (archive--file-desc-ext-file-name descr))
          (tmpfile (expand-file-name ename archive-tmpdir))
          (top (directory-file-name (file-name-as-directory archive-tmpdir)))
         (default-directory (file-name-as-directory top)))
@@ -1270,9 +1276,10 @@ using `make-temp-file', and the generated name is 
returned."
          ;; further processing clobbers it (we restore it in
          ;; archive-write-file-member, above).
          (setq archive-member-coding-system last-coding-system-used)
-         (if (aref descr 3)
+         (if (archive--file-desc-mode descr)
              ;; Set the file modes, but make sure we can read it.
-             (set-file-modes tmpfile (logior ?\400 (aref descr 3))))
+             (set-file-modes tmpfile
+                             (logior ?\400 (archive--file-desc-mode descr))))
          (setq ename
                (encode-coding-string ename archive-file-name-coding-system))
           (let* ((coding-system-for-write 'no-conversion)
@@ -1376,7 +1383,7 @@ Use \\[archive-unmark-all-files] to remove all marks."
   "Change the protection bits associated with all marked or this member.
 The new protection bits can either be specified as an octal number or
 as a relative change like \"g+rw\" as for chmod(2)."
-  (interactive "sNew mode (octal or relative): ")
+  (interactive "sNew mode (octal or symbolic): ")
   (if archive-read-only (error "Archive is read-only"))
   (let ((func (archive-name "chmod-entry")))
     (if (fboundp func)
@@ -1415,7 +1422,9 @@ as a relative change like \"g+rw\" as for chmod(2)."
       (goto-char archive-file-list-start)
       (while (< (point) archive-file-list-end)
         (if (= (following-char) ?D)
-           (setq files (cons (aref (archive-get-descr) 0) files)))
+           (setq files (cons (archive--file-desc-ext-file-name
+                              (archive-get-descr))
+                             files)))
         (forward-line 1)))
     (setq files (nreverse files))
     (and files
@@ -1461,12 +1470,11 @@ as a relative change like \"g+rw\" as for chmod(2)."
       (error "Renaming is not supported for this archive type"))))
 
 ;; Revert the buffer and recompute the dired-like listing.
-(defun archive-mode-revert (&optional _no-auto-save _no-confirm)
+(defun archive--mode-revert (orig-fun &rest args)
   (let ((no (archive-get-lineno)))
     (setq archive-files nil)
-    (let ((revert-buffer-function nil)
-         (coding-system-for-read 'no-conversion))
-      (revert-buffer t t))
+    (let ((coding-system-for-read 'no-conversion))
+      (apply orig-fun t t (cddr args)))
     (archive-mode)
     (goto-char archive-file-list-start)
     (archive-next-line no)))
@@ -1477,15 +1485,135 @@ This doesn't recover lost files, it just undoes 
changes in the buffer itself."
   (interactive)
   (let ((inhibit-read-only t))
     (undo)))
+
+(defun archive--fit (str len)
+  (let* ((spaces (- len (string-width str)))
+         (pre (/ spaces 2)))
+    (if (< spaces 1)
+        (substring str 0 len)
+      (concat (make-string pre ?\s) str (make-string (- spaces pre) ?\s)))))
+
+(defun archive--fit2 (str1 str2 len)
+  (let* ((spaces (- len (string-width str1) (string-width str2))))
+    (if (< spaces 1)
+        (substring (concat str1 str2) 0 len)
+      (concat str1 (make-string spaces ?\s) str2))))
+
+(defun archive--enabled-p (column)
+  (not (memq column archive-hidden-columns)))
+
+(defun archive--summarize-descs (descs)
+  (goto-char (point-min))
+  (if (null descs)
+      (progn (insert "M  ...   Filename\n")
+             (insert "- ----- ---------------\n")
+             (archive-summarize-files nil)
+             (insert "- ----- ---------------\n"))
+    (let* ((sample (car descs))
+           (maxsize 0)
+           (maxidlen 0)
+           (totalsize 0)
+           (times (archive--enabled-p 'Date&Time))
+           (ids (and (archive--enabled-p 'Ids)
+                     (or (archive--file-desc-uid sample)
+                         (archive--file-desc-gid sample))))
+           ;; For ratio, date/time, and mode, we presume that
+           ;; they're either present on all entries or on nonel, and that they
+           ;; take the same space on each of them.
+           (ratios (and (archive--enabled-p 'Ratio)
+                        (archive--file-desc-ratio sample)))
+           (ratiolen (if ratios (string-width ratios)))
+           (timelen (length (archive--file-desc-time sample)))
+           (samplemode (and (archive--enabled-p 'Mode)
+                            (archive--file-desc-mode sample)))
+           (modelen (length (if samplemode (archive-int-to-mode samplemode)))))
+      (dolist (desc descs)
+        (when ids
+          (let* ((uid (archive--file-desc-uid desc))
+                 (gid (archive--file-desc-uid desc))
+                 (len (cond
+                       ((not uid) (string-width gid))
+                       ((not gid) (string-width uid))
+                       (t (+ (string-width uid) (string-width gid) 1)))))
+            (if (> len maxidlen) (setq maxidlen len))))
+        (let ((size (archive--file-desc-size desc)))
+          (cl-incf totalsize size)
+          (if (> size maxsize) (setq maxsize size))))
+      (let* ((sizelen (length (number-to-string maxsize)))
+             (dash
+              (concat
+               "- "
+               (if (> modelen 0) (concat (make-string modelen ?-) "  "))
+               (if ids (concat (make-string maxidlen ?-) "  "))
+               (make-string sizelen ?-) " "
+               (if ratios (concat (make-string (1+ ratiolen) ?-) " "))
+               " "
+               (if times (concat (make-string timelen ?-) "  "))
+               "----------------\n"))
+             (startcol (+ 2
+                          (if (> modelen 0) (+ 2 modelen) 0)
+                          (if ids (+ maxidlen 2) 0)
+                          sizelen 2
+                          (if ratios (+ 2 ratiolen) 0)
+                          (if times (+ timelen 2) 0))))
+        (insert
+         (concat "M "
+                 (if (> modelen 0) (concat (archive--fit "Mode" modelen) "  "))
+                 (if ids (concat (archive--fit2 "Uid" "Gid" maxidlen) "  "))
+                 (archive--fit "Size" sizelen) " "
+                 (if ratios (concat (archive--fit "Cmp" (1+ ratiolen)) " "))
+                 " "
+                 (if times (concat (archive--fit "Date&time" timelen) "  "))
+                 " Filename\n"))
+        (insert dash)
+        (archive-summarize-files
+         (mapcar (lambda (desc)
+                   (let* ((size (number-to-string
+                                 (archive--file-desc-size desc)))
+                          (text
+                           (concat "  "
+                                   (when (> modelen 0)
+                                     (concat (archive-int-to-mode
+                                              (archive--file-desc-mode desc))
+                                             "  "))
+                                   (when ids
+                                     (concat (archive--fit2
+                                              (archive--file-desc-uid desc)
+                                              (archive--file-desc-gid desc)
+                                              maxidlen) "  "))
+                                   (make-string (- sizelen (length size)) ?\s)
+                                   size
+                                   " "
+                                   (when ratios
+                                     (concat (archive--file-desc-ratio desc)
+                                             "% "))
+                                   " "
+                                   (when times
+                                     (concat (archive--file-desc-time desc)
+                                             "  "))
+                                   (archive--file-desc-int-file-name desc))))
+                     (archive--file-summary
+                      text startcol (length text))))
+                 descs))
+        (insert dash)
+        (insert (format (format "%%%dd %%s %%d files\n"
+                                (+ 2
+                                   (if (> modelen 0) (+ 2 modelen) 0)
+                                   (if ids (+ maxidlen 2) 0)
+                                   sizelen))
+                        totalsize
+                        (make-string (+ (if times (+ 2 timelen) 0)
+                                        (if ratios (+ 2 ratiolen) 0) 1)
+                                     ?\s)
+                        (length descs))))))
+  (apply #'vector descs))
+
 ;; -------------------------------------------------------------------------
 ;;; Section: Arc Archives
 
 (defun archive-arc-summarize ()
   (let ((p 1)
-       (totalsize 0)
-       (maxlen 8)
-        files
-       visual)
+        files)
     (while (and (< (+ p 29) (point-max))
                (= (get-byte p) ?\C-z)
                (> (get-byte (1+ p)) 0))
@@ -1498,48 +1626,28 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
              (modtime (archive-l-e (+ p 21) 2))
              (ucsize  (archive-l-e (+ p 25) 4))
             (fiddle  (string= efnname (upcase efnname)))
-             (ifnname (if fiddle (downcase efnname) efnname))
-             (text    (format "  %8d  %-11s  %-8s  %s"
-                              ucsize
-                              (archive-dosdate moddate)
-                              (archive-dostime modtime)
-                              ifnname)))
-        (setq maxlen (max maxlen fnlen)
-             totalsize (+ totalsize ucsize)
-             visual (cons (vector text
-                                  (- (length text) (length ifnname))
-                                  (length text))
-                          visual)
-             files (cons (vector efnname ifnname fiddle nil (1- p))
+             (ifnname (if fiddle (downcase efnname) efnname)))
+        (setq files (cons (archive--file-desc
+                           efnname ifnname nil ucsize
+                           (concat (archive-dosdate moddate)
+                                   " " (archive-dostime modtime))
+                           :pos (1- p))
                           files)
               p (+ p 29 csize))))
-    (goto-char (point-min))
-    (let ((dash (concat "- --------  -----------  --------  "
-                       (make-string maxlen ?-)
-                       "\n")))
-      (insert "M   Length  Date         Time      File\n"
-             dash)
-      (archive-summarize-files (nreverse visual))
-      (insert dash
-             (format "  %8d                         %d file%s"
-                     totalsize
-                     (length files)
-                     (if (= 1 (length files)) "" "s"))
-             "\n"))
-    (apply #'vector (nreverse files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defun archive-arc-rename-entry (newname descr)
   (if (string-match "[:\\/]" newname)
       (error "File names in arc files must not contain a directory component"))
   (if (> (length newname) 12)
       (error "File names in arc files are limited to 12 characters"))
-  (let ((name (concat newname (substring "\0\0\0\0\0\0\0\0\0\0\0\0\0"
-                                        (length newname))))
+  (let ((name (concat newname (make-string (- 13 (length newname)) ?\0)))
        (inhibit-read-only t))
     (save-restriction
       (save-excursion
        (widen)
-       (goto-char (+ archive-proper-file-start (aref descr 4) 2))
+       (goto-char (+ archive-proper-file-start 2
+                     (archive--file-desc-pos descr)))
        (delete-char 13)
        (arc-insert-unibyte name)))))
 ;; -------------------------------------------------------------------------
@@ -1547,10 +1655,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
 
 (defun archive-lzh-summarize (&optional start)
   (let ((p (or start 1)) ;; 1 for .lzh, something further on for .exe
-       (totalsize 0)
-       (maxlen 8)
-        files
-       visual)
+        files)
     (while (progn (goto-char p)                ;beginning of a base header.
                  (looking-at "\\(.\\|\n\\)\\(.\\|\n\\)-l[hz][0-9ds]-"))
       (let* ((hsize   (get-byte p))    ;size of the base header (level 0 and 1)
@@ -1561,9 +1666,9 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
             (time2   (archive-l-e (+ p 17) 2)) ;and UNIX format in level 2 
header.)
             (hdrlvl  (get-byte (+ p 20))) ;header level
             thsize             ;total header size (base + extensions)
-            fnlen efnname osid fiddle ifnname width p2
+            fnlen efnname osid fiddle ifnname p2
             neh        ;beginning of next extension header (level 1 and 2)
-            mode modestr uid gid text dir prname
+            mode uid gid dir prname
             gname uname modtime moddate)
        (if (= hdrlvl 3) (error "can't handle lzh level 3 header type"))
        (when (or (= hdrlvl 0) (= hdrlvl 1))
@@ -1576,26 +1681,26 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
             (setq neh (+ p2 3))         ;specific to level 1 header
          (if (= hdrlvl 2)
               (setq neh (+ p 24))))     ;specific to level 2 header
-       (if neh         ;if level 1 or 2 we expect extension headers to follow
+       (if neh ;if level 1 or 2 we expect extension headers to follow
            (let* ((ehsize (archive-l-e neh 2)) ;size of the extension header
                   (etype (get-byte (+ neh 2)))) ;extension type
              (while (not (= ehsize 0))
-                 (cond
-                ((= etype 1)   ;file name
+               (cond
+                ((= etype 1)           ;file name
                  (let ((i (+ neh 3)))
                    (while (< i (+ neh ehsize))
                      (setq efnname (concat efnname (char-to-string (get-byte 
i))))
                      (setq i (1+ i)))))
-                ((= etype 2)   ;directory name
+                ((= etype 2)           ;directory name
                  (let ((i (+ neh 3)))
                    (while (< i (+ neh ehsize))
-                                   (setq dir (concat dir
-                                                      (if (= (get-byte i)
-                                                             255)
-                                                          "/"
-                                                        (char-to-string
-                                                         (char-after i)))))
-                                   (setq i (1+ i)))))
+                     (setq dir (concat dir
+                                       (if (= (get-byte i)
+                                              255)
+                                           "/"
+                                         (char-to-string
+                                          (char-after i)))))
+                     (setq i (1+ i)))))
                 ((= etype 80)          ;Unix file permission
                  (setq mode (archive-l-e (+ neh 3) 2)))
                 ((= etype 81)          ;UNIX file group/user ID
@@ -1611,7 +1716,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
                    (while (< i (+ neh ehsize))
                      (setq uname (concat uname (char-to-string (char-after 
i))))
                      (setq i (1+ i)))))
-                  )
+                )
                (setq neh (+ neh ehsize))
                (setq ehsize (archive-l-e neh 2))
                (setq etype (get-byte (+ neh 2))))
@@ -1637,60 +1742,25 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
                            ((= 0 osid)  (string= efnname (upcase efnname)))))
        (setq ifnname (if fiddle (downcase efnname) efnname))
        (setq prname (if dir (concat dir ifnname) ifnname))
-       (setq width (if prname (string-width prname) 0))
-       (setq modestr (if mode (archive-int-to-mode mode) "??????????"))
        (setq moddate (if (= hdrlvl 2)
                          (archive-unixdate time1 time2) ;level 2 header in 
UNIX format
                        (archive-dosdate time2))) ;level 0 and 1 header in DOS 
format
        (setq modtime (if (= hdrlvl 2)
                          (archive-unixtime time1 time2)
                        (archive-dostime time1)))
-       (setq text    (if archive-alternate-display
-                         (format "  %8d  %5S  %5S  %s"
-                                 ucsize
-                                 (or uid "?")
-                                 (or gid "?")
-                                 ifnname)
-                       (format "  %10s  %8d  %-11s  %-8s  %s"
-                               modestr
-                               ucsize
-                               moddate
-                               modtime
-                               prname)))
-        (setq maxlen (max maxlen width)
-             totalsize (+ totalsize ucsize)
-             visual (cons (vector text
-                                  (- (length text) (length prname))
-                                  (length text))
-                          visual)
-             files (cons (vector prname ifnname fiddle mode (1- p))
-                          files))
+        (push (archive--file-desc
+               prname ifnname mode ucsize
+               (concat moddate " " modtime)
+               :pos (1- p)
+               :uid (or uname (if uid (number-to-string uid)))
+               :gid (or gname (if gid (number-to-string gid))))
+              files)
        (cond ((= hdrlvl 1)
               (setq p (+ p hsize 2 csize)))
              ((or (= hdrlvl 2) (= hdrlvl 0))
               (setq p (+ p thsize 2 csize))))
        ))
-    (goto-char (point-min))
-    (let ((dash (concat (if archive-alternate-display
-                           "- --------  -----  -----  "
-                         "- ----------  --------  -----------  --------  ")
-                       (make-string maxlen ?-)
-                       "\n"))
-         (header (if archive-alternate-display
-                      "M   Length    Uid    Gid  File\n"
-                   "M   Filemode    Length  Date         Time      File\n"))
-         (sumline (if archive-alternate-display
-                      "  %8.0f                %d file%s"
-                    "              %8.0f                         %d file%s")))
-      (insert header dash)
-      (archive-summarize-files (nreverse visual))
-      (insert dash
-             (format sumline
-                     totalsize
-                     (length files)
-                     (if (= 1 (length files)) "" "s"))
-             "\n"))
-    (apply #'vector (nreverse files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defconst archive-lzh-alternate-display t)
 
@@ -1709,7 +1779,8 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
   (save-restriction
     (save-excursion
       (widen)
-      (let* ((p        (+ archive-proper-file-start (aref descr 4)))
+      (let* ((p        (+ archive-proper-file-start
+                         (archive--file-desc-pos descr)))
             (oldhsize (get-byte p))
             (oldfnlen (get-byte (+ p 21)))
             (newfnlen (length newname))
@@ -1729,7 +1800,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
     (save-restriction
       (widen)
       (dolist (fil files)
-       (let* ((p (+ archive-proper-file-start (aref fil 4)))
+       (let* ((p (+ archive-proper-file-start (archive--file-desc-pos fil)))
               (hsize   (get-byte p))
               (fnlen   (get-byte (+ p 21)))
               (p2      (+ p 22 fnlen))
@@ -1746,7 +1817,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
                (delete-char 1)
                (arc-insert-unibyte (archive-lzh-resum (1+ p) hsize)))
            (message "Member %s does not have %s field"
-                    (aref fil 1) errtxt)))))))
+                    (archive--file-desc-int-file-name fil) errtxt)))))))
 
 (defun archive-lzh-chown-entry (newuid files)
   (archive-lzh-ogm newuid files "an uid" 10))
@@ -1756,8 +1827,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
 
 (defun archive-lzh-chmod-entry (newmode files)
   (archive-lzh-ogm
-   ;; This should work even though newmode will be dynamically accessed.
-   (lambda (old) (archive-calc-mode old newmode t))
+   (lambda (old) (archive-calc-mode old newmode))
    files "a unix-style mode" 8))
 
 ;; -------------------------------------------------------------------------
@@ -1794,10 +1864,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
   (goto-char (- (point-max) (- 22 18)))
   (search-backward-regexp "[P]K\005\006")
   (let ((p (archive-l-e (+ (point) 16) 4))
-        (maxlen 8)
-       (totalsize 0)
-        files
-       visual)
+        files)
     (when (= p -1)
       ;; If the offset of end-of-central-directory is -1, this is a
       ;; Zip64 extended ZIP file format, and we need to glean the info
@@ -1823,7 +1890,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
              (fnlen   (archive-l-e (+ p 28) 2))
              (exlen   (archive-l-e (+ p 30) 2))
              (fclen   (archive-l-e (+ p 32) 2))
-             (lheader (archive-l-e (+ p 42) 4))
+             ;; (lheader (archive-l-e (+ p 42) 4))
              (efnname (let ((str (buffer-substring (+ p 46) (+ p 46 fnlen))))
                        (decode-coding-string
                         str archive-file-name-coding-system)))
@@ -1838,44 +1905,18 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
                                          (logand 1 (get-byte (+ p 38))))
                                         ?\222 0)))
                            (t nil)))
-            (modestr (if mode (archive-int-to-mode mode) "??????????"))
             (fiddle  (and archive-zip-case-fiddle
-                          (not (not (memq creator '(0 2 4 5 9))))
+                          (memq creator '(0 2 4 5 9))
                           (string= (upcase efnname) efnname)))
-             (ifnname (if fiddle (downcase efnname) efnname))
-            (width (string-width ifnname))
-             (text    (format "  %10s  %8d  %-11s  %-8s  %s"
-                             modestr
-                              ucsize
-                              (archive-dosdate moddate)
-                              (archive-dostime modtime)
-                              ifnname)))
-        (setq maxlen (max maxlen width)
-             totalsize (+ totalsize ucsize)
-             visual (cons (vector text
-                                  (- (length text) (length ifnname))
-                                  (length text))
-                          visual)
-             files (cons (if isdir
-                             nil
-                           (vector efnname ifnname fiddle mode
-                                   (list (1- p) lheader)))
-                          files)
+             (ifnname (if fiddle (downcase efnname) efnname)))
+        (setq files (cons (archive--file-desc
+                          efnname ifnname mode ucsize
+                          (concat (archive-dosdate moddate)
+                                  " " (archive-dostime modtime))
+                          :pos (1- p))
+                         files)
               p (+ p 46 fnlen exlen fclen))))
-    (goto-char (point-min))
-    (let ((dash (concat "- ----------  --------  -----------  --------  "
-                       (make-string maxlen ?-)
-                       "\n")))
-      (insert "M Filemode      Length  Date         Time      File\n"
-             dash)
-      (archive-summarize-files (nreverse visual))
-      (insert dash
-             (format "              %8d                         %d file%s"
-                     totalsize
-                     (length files)
-                     (if (= 1 (length files)) "" "s"))
-             "\n"))
-    (apply #'vector (nreverse files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defun archive-zip-extract (archive name)
   (cond
@@ -1900,21 +1941,27 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
        name)
      archive-zip-extract))))
 
+(defun archive--file-desc-case-fiddled (fd)
+  (not (eq (archive--file-desc-int-file-name fd)
+           (archive--file-desc-ext-file-name fd))))
+
 (defun archive-zip-write-file-member (archive descr)
   (archive-*-write-file-member
    archive
    descr
-   (if (aref descr 2) archive-zip-update-case archive-zip-update)))
+   (if (archive--file-desc-case-fiddled descr)
+       archive-zip-update-case archive-zip-update)))
 
 (defun archive-zip-chmod-entry (newmode files)
   (save-restriction
     (save-excursion
       (widen)
       (dolist (fil files)
-       (let* ((p (+ archive-proper-file-start (car (aref fil 4))))
+       (let* ((p (+ archive-proper-file-start
+                    (archive--file-desc-pos fil)))
               (creator (get-byte (+ p 5)))
-              (oldmode (aref fil 3))
-              (newval  (archive-calc-mode oldmode newmode t))
+              (oldmode (archive--file-desc-mode fil))
+              (newval  (archive-calc-mode oldmode newmode))
               (inhibit-read-only t))
          (cond ((memq creator '(2 3)) ; Unix
                 (goto-char (+ p 40))
@@ -1933,10 +1980,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
 
 (defun archive-zoo-summarize ()
   (let ((p (1+ (archive-l-e 25 4)))
-        (maxlen 8)
-       (totalsize 0)
-        files
-       visual)
+        files)
     (while (and (string= "\334\247\304\375" (buffer-substring p (+ p 4)))
                (> (archive-l-e (+ p 6) 4) 0))
       (let* ((next    (1+ (archive-l-e (+ p 6) 4)))
@@ -1963,36 +2007,14 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
                        (decode-coding-string
                         str archive-file-name-coding-system)))
             (fiddle  (and (= lfnlen 0) (string= efnname (upcase efnname))))
-             (ifnname (if fiddle (downcase efnname) efnname))
-            (width (string-width ifnname))
-             (text    (format "  %8d  %-11s  %-8s  %s"
-                              ucsize
-                              (archive-dosdate moddate)
-                              (archive-dostime modtime)
-                              ifnname)))
-        (setq maxlen (max maxlen width)
-             totalsize (+ totalsize ucsize)
-             visual (cons (vector text
-                                  (- (length text) (length ifnname))
-                                  (length text))
-                          visual)
-             files (cons (vector efnname ifnname fiddle nil (1- p))
+             (ifnname (if fiddle (downcase efnname) efnname)))
+        (setq files (cons (archive--file-desc
+                           efnname ifnname nil ucsize
+                           (concat (archive-dosdate moddate)
+                                   " " (archive-dostime modtime)))
                           files)
               p next)))
-    (goto-char (point-min))
-    (let ((dash (concat "- --------  -----------  --------  "
-                       (make-string maxlen ?-)
-                       "\n")))
-      (insert "M   Length  Date         Time      File\n"
-             dash)
-      (archive-summarize-files (nreverse visual))
-      (insert dash
-             (format "  %8d                         %d file%s"
-                     totalsize
-                     (length files)
-                     (if (= 1 (length files)) "" "s"))
-             "\n"))
-    (apply #'vector (nreverse files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defun archive-zoo-extract (archive name)
   (archive-extract-by-stdout archive name archive-zoo-extract))
@@ -2004,17 +2026,16 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
   ;; File is used internally for `archive-rar-exe-summarize'.
   (unless file (setq file buffer-file-name))
   (let* ((copy (file-local-copy file))
-         (maxname 10)
-         (maxsize 5)
          (files ()))
     (with-temp-buffer
-      (call-process "lsar" nil t nil "-l" (or file copy))
-      (if copy (delete-file copy))
+      (unwind-protect
+          (call-process "lsar" nil t nil "-l" (or file copy))
+        (if copy (delete-file copy)))
       (goto-char (point-min))
       (re-search-forward "^\\(\s+=+\s*\\)+\n")
       (while (looking-at (concat "^\s+[0-9.]+\s+D?-+\s+"   ; Flags
                                  "\\([0-9-]+\\)\s+"        ; Size
-                                 "\\([-0-9.%]+\\)\s+"      ; Ratio
+                                 "\\([-0-9.]+\\)%?\s+"      ; Ratio
                                  "\\([0-9a-zA-Z]+\\)\s+"   ; Mode
                                  "\\([0-9-]+\\)\s+"        ; Date
                                  "\\([0-9:]+\\)\s+"        ; Time
@@ -2023,36 +2044,14 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
         (goto-char (match-end 0))
         (let ((name (match-string 6))
               (size (match-string 1)))
-          (if (> (length name) maxname) (setq maxname (length name)))
-          (if (> (length size) maxsize) (setq maxsize (length size)))
-          (push (vector name name nil nil
-                        ;; Size, Ratio.
-                        size (match-string 2)
-                        ;; Date, Time.
-                        (match-string 4) (match-string 5))
+          (push (archive--file-desc name name nil
+                                    ;; Size
+                                    (string-to-number size)
+                                    ;; Date&Time.
+                                    (concat (match-string 4) " " (match-string 
5))
+                                    :ratio (match-string 2))
                 files))))
-    (setq files (nreverse files))
-    (goto-char (point-min))
-    (let* ((format (format " %%s %%s  %%%ds %%5s  %%s" maxsize))
-           (sep (format format "----------" "-----" (make-string maxsize ?-)
-                        "-----" ""))
-           (column (length sep)))
-      (insert (format format "   Date   " "Time " "Size" "Ratio" "Filename") 
"\n")
-      (insert sep (make-string maxname ?-) "\n")
-      (archive-summarize-files (mapcar (lambda (desc)
-                                         (let ((text
-                                                (format format
-                                                         (aref desc 6)
-                                                         (aref desc 7)
-                                                         (aref desc 4)
-                                                         (aref desc 5)
-                                                         (aref desc 1))))
-                                           (vector text
-                                                   column
-                                                   (length text))))
-                                       files))
-      (insert sep (make-string maxname ?-) "\n")
-      (apply #'vector files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defun archive-rar-extract (archive name)
   ;; unrar-free seems to have no way to extract to stdout or even to a file.
@@ -2099,9 +2098,7 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
 ;;; Section: 7z Archives
 
 (defun archive-7z-summarize ()
-  (let ((maxname 10)
-       (maxsize 5)
-       (file buffer-file-name)
+  (let ((file buffer-file-name)
        (files ()))
     (with-temp-buffer
       (call-process archive-7z-program nil t nil "l" "-slt" file)
@@ -2118,29 +2115,9 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
              (time (save-excursion
                      (and (re-search-forward "^Modified = \\(.*\\)\n")
                           (match-string 1)))))
-          (if (> (length name) maxname) (setq maxname (length name)))
-          (if (> (length size) maxsize) (setq maxsize (length size)))
-          (push (vector name name nil nil time nil nil size)
+          (push (archive--file-desc name name nil (string-to-number size) time)
                 files))))
-    (setq files (nreverse files))
-    (goto-char (point-min))
-    (let* ((format (format " %%%ds %%s %%s" maxsize))
-           (sep (format format (make-string maxsize ?-) "-------------------" 
""))
-           (column (length sep)))
-      (insert (format format "Size " "Date       Time    " " Filename") "\n")
-      (insert sep (make-string maxname ?-) "\n")
-      (archive-summarize-files (mapcar (lambda (desc)
-                                         (let ((text
-                                                (format format
-                                                       (aref desc 7)
-                                                       (aref desc 4)
-                                                       (aref desc 1))))
-                                           (vector text
-                                                   column
-                                                   (length text))))
-                                       files))
-      (insert sep (make-string maxname ?-) "\n")
-      (apply #'vector files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defun archive-7z-extract (archive name)
   ;; 7z doesn't provide a `quiet' option to suppress non-essential
@@ -2167,79 +2144,43 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
 (defconst archive-ar-file-header-re
   "\\(.\\{16\\}\\)\\([ 0-9]\\{12\\}\\)\\([ 0-9]\\{6\\}\\)\\([ 
0-9]\\{6\\}\\)\\([ 0-7]\\{8\\}\\)\\([ 0-9]\\{10\\}\\)`\n")
 
+(defun archive-ar--name (name)
+  "Return the external name represented by the entry NAME.
+NAME is expected to be the 16-bytes part of an ar record."
+  (cond ((equal name "//              ")
+         (propertize ".<ExtNamesTable>." 'face 'italic))
+        ((equal name "/               ")
+         (propertize ".<LookupTable>." 'face 'italic))
+        ((string-match "/? *\\'" name)
+         ;; FIXME: Decode?  Add support for longer names?
+         (substring name 0 (match-beginning 0)))))
+
 (defun archive-ar-summarize ()
   ;; File is used internally for `archive-rar-exe-summarize'.
-  (let* ((maxname 10)
-         (maxtime 16)
-         (maxuser 5)
-         (maxgroup 5)
-         (maxmode 8)
-         (maxsize 5)
-         (files ()))
+  (let* ((files ()))
     (goto-char (point-min))
     (search-forward "!<arch>\n")
     (while (looking-at archive-ar-file-header-re)
-      (let ((name (match-string 1))
-            extname
-            (time (string-to-number (match-string 2)))
-            (user (match-string 3))
-            (group (match-string 4))
-            (mode (string-to-number (match-string 5) 8))
-            (size (string-to-number (match-string 6))))
+      (let* ((name (match-string 1))
+             extname
+             (time (string-to-number (match-string 2)))
+             (user (match-string 3))
+             (group (match-string 4))
+             (mode (string-to-number (match-string 5) 8))
+             (sizestr (match-string 6))
+             (size (string-to-number sizestr)))
         ;; Move to the beginning of the data.
         (goto-char (match-end 0))
         (setq time (format-time-string "%Y-%m-%d %H:%M" time))
-        (setq extname
-              (cond ((equal name "//              ")
-                     (propertize ".<ExtNamesTable>." 'face 'italic))
-                    ((equal name "/               ")
-                     (propertize ".<LookupTable>." 'face 'italic))
-                    ((string-match "/? *\\'" name)
-                     (substring name 0 (match-beginning 0)))))
+        (setq extname (archive-ar--name name))
         (setq user (substring user 0 (string-match " +\\'" user)))
         (setq group (substring group 0 (string-match " +\\'" group)))
-        (setq mode (tar-grind-file-mode mode))
         ;; Move to the end of the data.
         (forward-char size) (if (eq ?\n (char-after)) (forward-char 1))
-        (setq size (number-to-string size))
-        (if (> (length name) maxname) (setq maxname (length name)))
-        (if (> (length time) maxtime) (setq maxtime (length time)))
-        (if (> (length user) maxuser) (setq maxuser (length user)))
-        (if (> (length group) maxgroup) (setq maxgroup (length group)))
-        (if (> (length mode) maxmode) (setq maxmode (length mode)))
-        (if (> (length size) maxsize) (setq maxsize (length size)))
-        (push (vector name extname nil mode
-                      time user group size)
+        (push (archive--file-desc extname extname mode size time
+                                  :uid user :gid group)
               files)))
-    (setq files (nreverse files))
-    (goto-char (point-min))
-    (let* ((format (format "%%%ds %%%ds/%%-%ds  %%%ds %%%ds %%s"
-                           maxmode maxuser maxgroup maxsize maxtime))
-           (sep (format format (make-string maxmode ?-)
-                         (make-string maxuser ?-)
-                          (make-string maxgroup ?-)
-                           (make-string maxsize ?-)
-                           (make-string maxtime ?-) ""))
-           (column (length sep)))
-      (insert (format format "  Mode  " "User" "Group" " Size "
-                      "      Date      " "Filename")
-              "\n")
-      (insert sep (make-string maxname ?-) "\n")
-      (archive-summarize-files (mapcar (lambda (desc)
-                                         (let ((text
-                                                (format format
-                                                         (aref desc 3)
-                                                         (aref desc 5)
-                                                         (aref desc 6)
-                                                         (aref desc 7)
-                                                         (aref desc 4)
-                                                         (aref desc 1))))
-                                           (vector text
-                                                   column
-                                                   (length text))))
-                                       files))
-      (insert sep (make-string maxname ?-) "\n")
-      (apply #'vector files))))
+    (archive--summarize-descs (nreverse files))))
 
 (defun archive-ar-extract (archive name)
   (let ((destbuf (current-buffer))
@@ -2256,10 +2197,11 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
             (let ((this (match-string 1)))
               (setq size (string-to-number (match-string 6)))
               (goto-char (match-end 0))
-              (if (equal name this)
+              (if (equal name (archive-ar--name this))
                   (setq from (point))
                 ;; Move to the end of the data.
-                (forward-char size) (if (eq ?\n (char-after)) (forward-char 
1)))))
+                (forward-char size)
+                (if (eq ?\n (char-after)) (forward-char 1)))))
           (when from
             (set-buffer-multibyte nil)
             (with-current-buffer destbuf
@@ -2269,6 +2211,13 @@ This doesn't recover lost files, it just undoes changes 
in the buffer itself."
             ;; Inform the caller that the call succeeded.
             t))))))
 
+(defun archive-ar-write-file-member (archive descr)
+  (archive-*-write-file-member
+   archive
+   descr
+   '("ar" "r")))
+
+
 ;; -------------------------------------------------------------------------
 ;; This line was a mistake; it is kept now for compatibility.
 ;; rms  15 Oct 98
diff --git a/lisp/faces.el b/lisp/faces.el
index 9a49ea8..e707f6f 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -1560,7 +1560,7 @@ is given, in which case return its value instead."
     ;; return it to the caller. Since there will most definitely be something 
to
     ;; return in this case, there's no need to know/check if a match was found.
     (if defaults
-       (append result defaults)
+       (append defaults result)
       (if match-found
          result
        no-match-retval))))
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index bccef68..aa3f7d3 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -11685,7 +11685,16 @@ comment at the start of cc-engine.el for more info."
                                     (not (c-in-literal))
                                     ))))
                           nil)
-                         (t t))))))
+                         (t t)))))
+               ((and
+                 (c-major-mode-is 'c++-mode)
+                 (eq (char-after) ?\[)
+                ;; Be careful of "operator []"
+                 (not (save-excursion
+                        (c-backward-token-2 1 nil lim)
+                        (looking-at c-opt-op-identifier-prefix))))
+                (setq braceassignp t)
+                nil))
          (when (eq braceassignp 'dontknow)
            (cond ((and
                    (not (eq (char-after) ?,))
@@ -12057,7 +12066,7 @@ comment at the start of cc-engine.el for more info."
                         (c-backward-token-2 1 nil lim)
                         (and
                          (not (and (c-on-identifier)
-                                   (looking-at c-symbol-chars)))
+                                   (looking-at c-symbol-char-key)))
                          (not (looking-at c-opt-op-identifier-prefix)))))))
            (cons 'inlambda bracket-pos))
           ((and c-recognize-paren-inexpr-blocks
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 7fb3687..0750683 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1850,7 +1850,8 @@ static char *magick[] = {
    "\\|def\\(i\\(ne?\\)?\\)?\\|doc\\(u\\(m\\(e\\(nt?\\)?\\)?\\)?\\)?\\|"
    gdb-python-guile-commands-regexp
    "\\|while-stepping\\|stepp\\(i\\(ng?\\)?\\)?\\|ws\\|actions"
-   "\\)\\([[:blank:]]+\\([^[:blank:]]*\\)\\)?$")
+   "\\|expl\\(o\\(r\\e?\\)?\\)?"
+   "\\)\\([[:blank:]]+\\([^[:blank:]]*\\)\\)*$")
   "Regexp matching GDB commands that enter a recursive reading loop.
 As long as GDB is in the recursive reading loop, it does not expect
 commands to be prefixed by \"-interpreter-exec console\".")
@@ -2508,7 +2509,13 @@ file names include non-ASCII characters."
 
   gdb-filter-output)
 
-(defun gdb-gdb (_output-field))
+(defun gdb-gdb (_output-field)
+  ;; This is needed because the "explore" command is not ended by the
+  ;; likes of "end" or "quit", but instead by a RET at the approriate
+  ;; place, and we know we have exited "explore" when we get the
+  ;; "(gdb)" prompt.
+  (and (> gdb-control-level 0)
+       (setq gdb-control-level (1- gdb-control-level))))
 
 (defun gdb-shell (output-field)
   (setq gdb-filter-output
diff --git a/src/Makefile.in b/src/Makefile.in
index 8d7fdb8..429f703 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -381,11 +381,14 @@ endif
 # Flags that might be in WARN_CFLAGS but are not valid for Objective C.
 NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd
 
+# Cajole GCC into inlining key ops even if it wouldn't normally.
+KEY_OPS_CFLAGS = $(if $(filter -Og,$(CFLAGS)),-DDEFINE_KEY_OPS_AS_MACROS)
+
 # -Demacs makes some files produce the correct version for use in Emacs.
 # MYCPPFLAGS is for by-hand Emacs-specific overrides, e.g.,
 # "make MYCPPFLAGS='-DDBUS_DEBUG'".
-EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
-  -I$(lib) -I$(top_srcdir)/lib \
+EMACS_CFLAGS = -Demacs $(KEY_OPS_CFLAGS) $(MYCPPFLAGS) \
+  -I. -I$(srcdir) -I$(lib) -I$(top_srcdir)/lib \
   $(C_SWITCH_MACHINE) $(C_SWITCH_SYSTEM) $(C_SWITCH_X_SITE) \
   $(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
   $(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
diff --git a/src/character.c b/src/character.c
index d71cb3f..a566cac 100644
--- a/src/character.c
+++ b/src/character.c
@@ -849,24 +849,22 @@ Concatenate all the argument characters and make the 
result a string.
 usage: (string &rest CHARACTERS)  */)
   (ptrdiff_t n, Lisp_Object *args)
 {
-  ptrdiff_t i;
-  int c;
-  unsigned char *buf, *p;
-  Lisp_Object str;
-  USE_SAFE_ALLOCA;
-
-  SAFE_NALLOCA (buf, MAX_MULTIBYTE_LENGTH, n);
-  p = buf;
-
-  for (i = 0; i < n; i++)
+  ptrdiff_t nbytes = 0;
+  for (ptrdiff_t i = 0; i < n; i++)
     {
       CHECK_CHARACTER (args[i]);
-      c = XFIXNUM (args[i]);
+      nbytes += CHAR_BYTES (XFIXNUM (args[i]));
+    }
+  if (nbytes == n)
+    return Funibyte_string (n, args);
+  Lisp_Object str = make_uninit_multibyte_string (n, nbytes);
+  unsigned char *p = SDATA (str);
+  for (ptrdiff_t i = 0; i < n; i++)
+    {
+      eassume (CHARACTERP (args[i]));
+      int c = XFIXNUM (args[i]);
       p += CHAR_STRING (c, p);
     }
-
-  str = make_string_from_bytes ((char *) buf, n, p - buf);
-  SAFE_FREE ();
   return str;
 }
 
@@ -875,20 +873,13 @@ DEFUN ("unibyte-string", Funibyte_string, 
Sunibyte_string, 0, MANY, 0,
 usage: (unibyte-string &rest BYTES)  */)
   (ptrdiff_t n, Lisp_Object *args)
 {
-  ptrdiff_t i;
-  Lisp_Object str;
-  USE_SAFE_ALLOCA;
-  unsigned char *buf = SAFE_ALLOCA (n);
-  unsigned char *p = buf;
-
-  for (i = 0; i < n; i++)
+  Lisp_Object str = make_uninit_string (n);
+  unsigned char *p = SDATA (str);
+  for (ptrdiff_t i = 0; i < n; i++)
     {
       CHECK_RANGED_INTEGER (args[i], 0, 255);
       *p++ = XFIXNUM (args[i]);
     }
-
-  str = make_string_from_bytes ((char *) buf, n, p - buf);
-  SAFE_FREE ();
   return str;
 }
 
diff --git a/src/lisp.h b/src/lisp.h
index 2f719b1..1a5215d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -411,15 +411,19 @@ typedef EMACS_INT Lisp_Word;
 # define lisp_h_XTYPE(a) ((enum Lisp_Type) (XLI (a) & ~VALMASK))
 #endif
 
-/* When compiling via gcc -O0, define the key operations as macros, as
-   Emacs is too slow otherwise.  To disable this optimization, compile
-   with -DINLINING=false.  */
-#if (defined __NO_INLINE__ \
-     && ! defined __OPTIMIZE__ && ! defined __OPTIMIZE_SIZE__ \
-     && ! (defined INLINING && ! INLINING))
-# define DEFINE_KEY_OPS_AS_MACROS true
-#else
-# define DEFINE_KEY_OPS_AS_MACROS false
+/* When DEFINE_KEY_OPS_AS_MACROS, define key operations as macros to
+   cajole the compiler into inlining them; otherwise define them as
+   inline functions as this is cleaner and can be more efficient.
+   The default is true if the compiler is GCC-like and if function
+   inlining is disabled because the compiler is not optimizing or is
+   optimizing for size.  Otherwise the default is false.  */
+#ifndef DEFINE_KEY_OPS_AS_MACROS
+# if (defined __NO_INLINE__ \
+      && ! defined __OPTIMIZE__ && ! defined __OPTIMIZE_SIZE__)
+#  define DEFINE_KEY_OPS_AS_MACROS true
+# else
+#  define DEFINE_KEY_OPS_AS_MACROS false
+# endif
 #endif
 
 #if DEFINE_KEY_OPS_AS_MACROS



reply via email to

[Prev in Thread] Current Thread [Next in Thread]