unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Scan of Emacs regexp mistakes
@ 2020-04-05 12:30 Mattias Engdegård
  2020-04-14 10:52 ` Mattias Engdegård
  0 siblings, 1 reply; 10+ messages in thread
From: Mattias Engdegård @ 2020-04-05 12:30 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 526 bytes --]

A new scan of irregularities and errors in regexps in the Emacs tree, using an experimental version of relint/xr.
New checks include ones specific to file names, more elaborate subsumption checks, and rx-specific checks. All are designed to avoid false positives; comments are very welcome!

For an explanation of individual diagnostics, see
https://github.com/mattiase/relint/blob/master/README.
Do ask if you find anything unclear.

(I will take care of those in rx-tests.el; they probably just need suppressing.)


[-- Attachment #2: relint.log --]
[-- Type: application/octet-stream, Size: 15861 bytes --]

Relint results for ~/emacs      -*- compilation -*-
lisp/calendar/todo-mode.el:710:66: Use \' instead of $ in file-matching regexp (pos 8)
  ".*\\.todr$"
   .........^
lisp/calendar/todo-mode.el:4057:62: Use \' instead of $ in file-matching regexp (pos 10)
  "\\.tod[rty]$"
   ...........^
lisp/calendar/todo-mode.el:4190:65: Use \' instead of $ in file-matching regexp (pos 8)
  ".*\\.todr$"
   .........^
lisp/calendar/todo-mode.el:6157:71: Use \' instead of $ in file-matching regexp (pos 10)
  "\\.tod[rty]$"
   ...........^
lisp/calendar/todo-mode.el:6210:66: Use \' instead of $ in file-matching regexp (pos 6)
  "\\.todr$"
   .......^
lisp/calendar/todo-mode.el:6239:66: Use \' instead of $ in file-matching regexp (pos 6)
  "\\.todr$"
   .......^
lisp/calendar/todo-mode.el:6265:70: Use \' instead of $ in file-matching regexp (pos 10)
  "\\.tod[rty]$"
   ...........^
lisp/cedet/semantic/db-ebrowse.el:184:31: Possibly unescaped ‘.’ in file-matching regexp (pos 11)
  "BROWSE-load.el$"
   ...........^
lisp/cedet/semantic/db-ebrowse.el:184:31: Use \' instead of $ in file-matching regexp (pos 14)
  "BROWSE-load.el$"
   ..............^
lisp/cedet/semantic/texi.el:498:59: Use \' instead of $ in file-matching regexp (pos 6)
  "\\.texi$"
   .......^
lisp/cedet/srecode/map.el:330:50: Use \' instead of $ in file-matching regexp (pos 5)
  "\\.srt$"
   ......^
lisp/emacs-lisp/autoload.el:1054:53: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^=.].*\\(\\`a\\`\\)\\'"
   ^
lisp/emacs-lisp/shadow.el:102:56: Possibly unescaped ‘.’ in file-matching regexp (pos 0)
  ".\\.elc?\\(\\.gz\\)?$"
   ^
lisp/emacs-lisp/shadow.el:102:76: Use \' instead of $ in file-matching regexp (pos 16)
  ".\\.elc?\\(\\.gz\\)?$"
   ....................^
lisp/erc/erc-dcc.el:634:39: In erc-dcc-ctcp-query-send-regexp: Repetition of expression matching an empty string (pos 30)
  "^DCC SEND \\(\"\\(\\(.*?\\(\\\\\"\\)?\\)+?\\)\"\\|\\([^ ]+\\)\\) \\([0-9]+\\) \\([0-9]+\\) *\\([0-9]*\\)"
   ........................................^
lisp/gnus/gnus-agent.el:2077:42: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/gnus-agent.el:2077:49: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/gnus-agent.el:3853:78: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/gnus-agent.el:3853:85: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/gnus-agent.el:4113:37: Use \` instead of ^ in file-matching regexp (pos 0)
  "^-?[0-9]+$"
   ^
lisp/gnus/gnus-agent.el:4113:46: Use \' instead of $ in file-matching regexp (pos 9)
  "^-?[0-9]+$"
   .........^
lisp/gnus/gnus-cache.el:504:53: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/gnus-cache.el:504:60: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/gnus-score.el:2984:29: Use \' instead of $ in file-matching regexp (pos 18)
  "\\(SCORE\\|ADAPT\\)\\'$"
   ......................^
lisp/gnus/gnus-util.el:771:32: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/gnus/gnus-util.el:771:59: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/gnus/gnus-uu.el:1677:56: Use \' instead of $ in file-matching regexp (pos 15)
  "[^/][^\\.][^\\.]?$"
   .................^
lisp/gnus/nndraft.el:222:55: Use \` instead of ^ in file-matching regexp (pos 0)
  "^#[0-9]+#$"
   ^
lisp/gnus/nndraft.el:222:64: Use \' instead of $ in file-matching regexp (pos 9)
  "^#[0-9]+#$"
   .........^
lisp/gnus/nnmh.el:175:55: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/nnmh.el:175:62: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/nnmh.el:363:60: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/nnmh.el:363:67: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/nnmh.el:374:64: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/nnmh.el:374:71: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/nnmh.el:488:55: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/nnmh.el:488:62: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/nnmh.el:512:53: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/nnmh.el:512:60: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/nnspool.el:263:56: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[0-9]+$"
   ^
lisp/gnus/nnspool.el:263:63: Use \' instead of $ in file-matching regexp (pos 7)
  "^[0-9]+$"
   .......^
lisp/gnus/spam-stat.el:560:41: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^.]"
   ^
lisp/gnus/spam-stat.el:604:41: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^.]"
   ^
lisp/international/quail.el:3062:61: Use \' instead of $ in file-matching regexp (pos 4)
  "\\.el$"
   .....^
lisp/international/titdic-cnv.el:556:62: Use \' instead of $ in file-matching regexp (pos 5)
  "\\.tit$"
   ......^
lisp/mail/mspools.el:226:38: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^.]+\\.spool"
   ^
lisp/mail/mspools.el:360:36: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^.]+\\.spool$"
   ^
lisp/mail/mspools.el:360:36: Use \' instead of $ in file-matching regexp (pos 13)
  "^[^.]+\\.spool$"
   ..............^
lisp/mail/rmail.el:1638:46: Use \' instead of $ in file-matching regexp (pos 7)
  "\\.xmail$"
   ........^
lisp/mail/rmail.el:4426:39: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[A-Z0-9]+\\(\\.[A-Z0-9]+\\)?$"
   ^
lisp/mail/rmail.el:4426:39: Use \' instead of $ in file-matching regexp (pos 26)
  "^[A-Z0-9]+\\(\\.[A-Z0-9]+\\)?$"
   .............................^
lisp/net/ange-ftp.el:4174:26: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/net/ange-ftp.el:4174:53: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/net/puny.el:38:36: In call to string-match: End-of-text anchor followed by non-empty pattern (pos 13)
  "\\'[[:ascii:]]+\\'"
   ..............^
lisp/net/tramp-adb.el:59:56: In tramp-adb-prompt: Repetition subsumes preceding repetition (pos 50)
  "^[[:digit:]]*|?[[:alnum:]\e;[]*@?[[:alnum:]]*[^#\\$]*[#\\$][[:space:]]"
   ....................................................^
lisp/net/tramp-loaddefs.el:23:80: In tramp-adb-prompt: Repetition subsumes preceding repetition (pos 50)
  "^[[:digit:]]*|?[[:alnum:]\e;[]*@?[[:alnum:]]*[^#\\$]*[#\\$][[:space:]]"
   ....................................................^
lisp/net/tramp.el:2467:40: Use \` instead of ^ in file-matching regexp (pos 0)
  "^tramp.+\\.elc?$"
   ^
lisp/net/tramp.el:2467:55: Use \' instead of $ in file-matching regexp (pos 14)
  "^tramp.+\\.elc?$"
   ...............^
lisp/obsolete/gulp.el:97:49: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^=].*\\.el$"
   ^
lisp/obsolete/gulp.el:97:61: Use \' instead of $ in file-matching regexp (pos 11)
  "^[^=].*\\.el$"
   ............^
lisp/obsolete/vc-arch.el:600:60: Possibly unescaped ‘.’ in file-matching regexp (pos 6)
  "[^.]\\|..."
   .......^
lisp/obsolete/vc-arch.el:600:61: Possibly unescaped ‘.’ in file-matching regexp (pos 7)
  "[^.]\\|..."
   ........^
lisp/obsolete/vc-arch.el:600:62: Possibly unescaped ‘.’ in file-matching regexp (pos 8)
  "[^.]\\|..."
   .........^
lisp/obsolete/vc-arch.el:605:67: Possibly unescaped ‘.’ in file-matching regexp (pos 6)
  "[^.]\\|..."
   .......^
lisp/obsolete/vc-arch.el:605:68: Possibly unescaped ‘.’ in file-matching regexp (pos 7)
  "[^.]\\|..."
   ........^
lisp/obsolete/vc-arch.el:605:69: Possibly unescaped ‘.’ in file-matching regexp (pos 8)
  "[^.]\\|..."
   .........^
lisp/obsolete/vc-arch.el:611:67: Possibly unescaped ‘.’ in file-matching regexp (pos 6)
  "[^.]\\|..."
   .......^
lisp/obsolete/vc-arch.el:611:68: Possibly unescaped ‘.’ in file-matching regexp (pos 7)
  "[^.]\\|..."
   ........^
lisp/obsolete/vc-arch.el:611:69: Possibly unescaped ‘.’ in file-matching regexp (pos 8)
  "[^.]\\|..."
   .........^
lisp/org/ob-core.el:3058:35: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/org/ob-core.el:3058:62: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/org/org-table.el:2008:52: In call to re-search-forward: Last item in repetition subsumes first item (wrapped) (pos 15)
  "\\([ \t]*\n[ \t]*\\)+"
   ....................^
lisp/progmodes/ebnf2ps.el:4944:35: Use \' instead of $ in file-matching regexp (pos 14)
  "\\.[Bb][Nn][Ff]$"
   ...............^
lisp/progmodes/executable.el:158:47: Use \` instead of ^ in file-matching regexp (pos 0)
  "^[^.]"
   ^
lisp/progmodes/gdb-mi.el:1847:3: In gdb-control-commands-regexp: Escaped non-special character ‘e’ (pos 205)
  "^\\(comm\\(a\\(n\\(ds?\\)?\\)?\\)?\\|if\\|while\\|def\\(i\\(ne?\\)?\\)?\\|doc\\(u\\(m\\(e\\(nt?\\)?\\)?\\)?\\)?\\|python\\|python-interactive\\|pi\\|guile\\|guile-repl\\|gr\\|while-stepping\\|stepp\\(i\\(ng?\\)?\\)?\\|ws\\|actions\\|expl\\(o\\(r\\e?\\)?\\)?\\)\\([[:blank:]]+\\([^[:blank:]]*\\)\\)*$"
   .....................................................................................................................................................................................................................................................^
lisp/progmodes/scheme.el:150:40: In imenu-generic-expression: Repetition of expression matching an empty string (pos 50)
  "^(define\\(\\|-\\(generic\\(\\|-procedure\\)\\|method\\)\\)*\\s-+(?\\(\\sw+\\)"
   ...........................................................^
lisp/textmodes/refer.el:380:62: Use \' instead of $ in file-matching regexp (pos 5)
  "\\.bib$"
   ......^
lisp/textmodes/sgml-mode.el:290:32: In sgml-start-tag-regex: Repetition subsumes preceding repetition (pos 62)
  "<[_:[:alpha:]][-_.:[:alnum:]]*\\(?:[^\"'/><]\\|\"[^\"]*\"\\|'[^']*'\\)*"
   ......................................................................^
lisp/textmodes/sgml-mode.el:597:31: In paragraph-start: Repetition subsumes preceding repetition (pos 79)
  "[ \t]*$\\|[ \t]*</?\\([_:[:alpha:]][-_.:[:alnum:]]*\\(?:[^\"'/><]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?>"
   ...........................................................................................^
lisp/url/url-about.el:40:57: Use \` instead of ^ in file-matching regexp (pos 0)
  "^url-.*\\.el$"
   ^
lisp/url/url-about.el:40:69: Use \' instead of $ in file-matching regexp (pos 11)
  "^url-.*\\.el$"
   ............^
lisp/vc/diff-mode.el:1463:8: In imenu-generic-expression: Escaped non-special character ‘ ’ (pos 6)
  "\\+\\+\\+\\ \\([^\t\n]+\\)[\t\n]"
   .........^
lisp/vc/vc-rcs.el:250:43: Use \' instead of $ in file-matching regexp (pos 4)
  ".*,v$"
   ....^
lisp/vc/vc-rcs.el:316:35: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.[^.]\\|\\.\\.[^.]\\).*"
   ^
lisp/arc-mode.el:2035:42: In call to re-search-forward: First item in repetition subsumes last item (wrapped) (pos 11)
  "^\\( +=+ *\\)+\n"
   .............^
lisp/auth-source-pass.el:193:52: Use \' instead of $ in file-matching regexp (pos 5)
  "\\.gpg$"
   ......^
lisp/dired.el:3261:60: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/dired.el:3261:60: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/files.el:2638:3: Possibly unescaped ‘.’ in file-matching regexp (pos 8)
  "\\.ad[bs].dg\\'"
   .........^
lisp/files.el:2638:3: Possibly unescaped ‘.’ in file-matching regexp (pos 11)
  "/\\.redshift.conf\\'"
   ............^
lisp/files.el:5785:41: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/files.el:5785:41: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/files.el:5807:33: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/files.el:5807:33: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/files.el:5930:33: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ^
lisp/files.el:5930:33: Possibly unescaped ‘.’ in file-matching regexp (pos 21)
  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
   ...........................^
lisp/finder.el:198:57: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\([^=].*\\)\\.el\\(\\.\\(gz\\|Z\\)\\)?$"
   ^
lisp/finder.el:198:57: Use \' instead of $ in file-matching regexp (pos 31)
  "^\\([^=].*\\)\\.el\\(\\.\\(gz\\|Z\\)\\)?$"
   ........................................^
lisp/generic-x.el:1433:16: Possibly unescaped ‘.’ in file-matching regexp (pos 10)
  "/etc/inetd.conf\\'"
   ..........^
lisp/generic-x.el:1633:16: Possibly unescaped ‘.’ in file-matching regexp (pos 10)
  "/etc/named.boot\\'"
   ..........^
lisp/generic-x.el:1670:21: Possibly unescaped ‘.’ in file-matching regexp (pos 15)
  "/etc/resolv[e]?.conf\\'"
   ...............^
lisp/generic-x.el:1806:18: Possibly unescaped ‘.’ in file-matching regexp (pos 12)
  "/etc/modules.conf"
   ............^
lisp/generic-x.el:1806:35: Possibly unescaped ‘.’ in file-matching regexp (pos 9)
  "/etc/conf.modules"
   .........^
lisp/help-fns.el:626:58: Possibly unescaped ‘.’ in file-matching regexp (pos 6)
  "\\`NEWS.[1-9]"
   .......^
lisp/help.el:364:40: Use \` instead of ^ in file-matching regexp (pos 0)
  "^NEWS\\.[0-9][-0-9]*$"
   ^
lisp/help.el:364:60: Use \' instead of $ in file-matching regexp (pos 19)
  "^NEWS\\.[0-9][-0-9]*$"
   ....................^
lisp/startup.el:1376:36: Use \` instead of ^ in file-matching regexp (pos 0)
  "^\\.emacs\\(\\.elc?\\)?$"
   ^
lisp/startup.el:1376:59: Use \' instead of $ in file-matching regexp (pos 19)
  "^\\.emacs\\(\\.elc?\\)?$"
   .......................^
lisp/startup.el:1379:36: Use \` instead of ^ in file-matching regexp (pos 0)
  "^_emacs\\(\\.elc?\\)?$"
   ^
lisp/startup.el:1379:57: Use \' instead of $ in file-matching regexp (pos 18)
  "^_emacs\\(\\.elc?\\)?$"
   .....................^
test/lisp/emacs-lisp/rx-tests.el:66:51: Range ‘<-]’ overlaps previous ‘]-{’
test/lisp/emacs-lisp/rx-tests.el:130:34: Duplicated character ‘-’ (pos 1)
  "c-"
   .^
test/lisp/emacs-lisp/rx-tests.el:130:38: Single-character range ‘f-f’ (pos 0)
  "f-f"
   ^
test/lisp/emacs-lisp/rx-tests.el:130:44: Range ‘--/’ overlaps previous ‘-’ (pos 0)
  "--/*--"
   ^
test/lisp/emacs-lisp/rx-tests.el:130:47: Range ‘*--’ overlaps previous ‘--/’ (pos 3)
  "--/*--"
   ...^
test/lisp/emacs-lisp/rx-tests.el:143:42: Duplicated class ‘space’
test/lisp/net/tramp-archive-tests.el:671:68: Use \` instead of ^ in file-matching regexp (pos 0)
  "^b"
   ^
test/lisp/net/tramp-tests.el:3356:71: Use \` instead of ^ in file-matching regexp (pos 0)
  "^b"
   ^

Finished -- 118 errors (2 suppressed).

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-05 12:30 Scan of Emacs regexp mistakes Mattias Engdegård
@ 2020-04-14 10:52 ` Mattias Engdegård
  2020-04-14 11:15   ` Andreas Schwab
                     ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Mattias Engdegård @ 2020-04-14 10:52 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 858 bytes --]

5 apr. 2020 kl. 14.30 skrev Mattias Engdegård <mattiase@acm.org>:

> A new scan of irregularities and errors in regexps in the Emacs tree, using an experimental version of relint/xr.

The filename-matching regexp glitches were fixed separately by the attached patch, pushed to emacs-27, since these were actual or latent bugs.

Several different regexps were used for matching anything but "." and "..", all wrong. These were all replaced with the concise and correct (rx (or (not ".") "...")), meaning "[^.]\\|\\.\\.\\." for traditionalists.

It is quite clear that returning . and .. from directory-files etc was a mistake; they are practically never useful but requires callers to take steps to filter them out. It's likely that nothing would break if we stopped returning those entries, but that is not a change that I'm proposing right now.


[-- Attachment #2: fix-file-matching-regexps.patch --]
[-- Type: application/octet-stream, Size: 34706 bytes --]

 admin/authors.el                     |  8 ++++----
 lisp/auth-source-pass.el             |  2 +-
 lisp/calendar/todo-mode.el           | 14 +++++++-------
 lisp/cedet/semantic/db-ebrowse.el    |  4 +++-
 lisp/cedet/semantic/texi.el          |  2 +-
 lisp/cedet/srecode/map.el            |  2 +-
 lisp/dired.el                        |  2 +-
 lisp/emacs-lisp/autoload.el          |  2 +-
 lisp/emacs-lisp/shadow.el            |  3 ++-
 lisp/files.el                        |  6 +++---
 lisp/finder.el                       |  2 +-
 lisp/generic-x.el                    |  8 ++++----
 lisp/gnus/gnus-agent.el              |  7 ++++---
 lisp/gnus/gnus-cache.el              |  2 +-
 lisp/gnus/gnus-score.el              |  2 +-
 lisp/gnus/gnus-util.el               |  2 +-
 lisp/gnus/gnus-uu.el                 |  2 +-
 lisp/gnus/nndraft.el                 |  2 +-
 lisp/gnus/nnmh.el                    | 10 +++++-----
 lisp/gnus/nnspool.el                 |  2 +-
 lisp/gnus/spam-stat.el               |  4 ++--
 lisp/help-fns.el                     |  2 +-
 lisp/help.el                         |  2 +-
 lisp/international/quail.el          |  2 +-
 lisp/international/titdic-cnv.el     |  2 +-
 lisp/mail/mspools.el                 |  4 ++--
 lisp/mail/rmail.el                   |  5 +++--
 lisp/net/ange-ftp.el                 |  3 +--
 lisp/net/tramp.el                    |  2 +-
 lisp/obsolete/gulp.el                |  2 +-
 lisp/obsolete/vc-arch.el             |  8 +++++---
 lisp/org/ob-core.el                  |  2 +-
 lisp/progmodes/ebnf2ps.el            |  4 ++--
 lisp/progmodes/executable.el         |  2 +-
 lisp/startup.el                      |  4 ++--
 lisp/textmodes/refer.el              |  2 +-
 lisp/url/url-about.el                |  2 +-
 lisp/vc/vc-rcs.el                    |  5 ++---
 test/lisp/net/tramp-archive-tests.el |  2 +-
 test/lisp/net/tramp-tests.el         |  2 +-
 40 files changed, 75 insertions(+), 70 deletions(-)

diff --git a/admin/authors.el b/admin/authors.el
index dc42bc72ef..6cf7b95449 100644
--- a/admin/authors.el
+++ b/admin/authors.el
@@ -278,7 +278,7 @@ authors-public-domain-files
 
 
 (defvar authors-obsolete-files-regexps
-  '(".*loaddefs.el$"			; not obsolete, but auto-generated
+  '(".*loaddefs\\.el$"			; not obsolete, but auto-generated
     "\\.\\(bzr\\|cvs\\|git\\)ignore$"		; obsolete or uninteresting
     "\\.arch-inventory$"
     "ChangeLog\\(\\.[0-9]+\\)?\\'"
@@ -288,9 +288,9 @@ authors-obsolete-files-regexps
     "\\`\\(indent\\|automated\\)\\'" "indent/" "mod-test/"
     "-resources/"
     "unidata/.*\\.txt\\'"
-    "BidiCharacterTest.txt"
+    "BidiCharacterTest\\.txt"
     ;; TODO lib/? Matches other things?
-    "build-aux/" "m4/" "Emacs.xcodeproj" "mapfiles" "\\.map\\'"
+    "build-aux/" "m4/" "Emacs\\.xcodeproj" "mapfiles" "\\.map\\'"
     "preferences\\.\\(nib\\|gorm\\)"
     ;; Generated files that have since been removed.
     "\\(refcard\\(-de\\|-pl\\)?\\|calccard\\|dired-ref\\|orgcard\\|\
@@ -1183,7 +1183,7 @@ authors-renamed-files-regexps
     ("\\`org-\\(ascii\\|beamer\\|html\\|icalendar\\|jsinfo\\|latex\
 \\|odt\\|publish\\)\\.el\\'" "ox-\\1.el")
     ;; From test/ to test/automated/.
-    ("comint-testsuite.el" "automated/\\&")
+    ("comint-testsuite\\.el" "automated/\\&")
     ("\\`\\(bytecomp\\|font-parse\\|icalendar\\|occur\\|newsticker\\)\
 -testsuite\\.el" "\\1-tests.el")
     ("automated/flymake/warnpred/\\(Makefile\\|test\\.\\(?:c\\|pl\\)\\)\\'"
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index e2a6bfefb5..ba66d0bb5d 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -190,7 +190,7 @@ auth-source-pass-entries
   (let ((store-dir (expand-file-name auth-source-pass-filename)))
     (mapcar
      (lambda (file) (file-name-sans-extension (file-relative-name file store-dir)))
-     (directory-files-recursively store-dir "\\.gpg$"))))
+     (directory-files-recursively store-dir "\\.gpg\\'"))))
 
 (defun auth-source-pass--find-match (host user port)
   "Return password-store entry data matching HOST, USER and PORT.
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 6d8fe9c998..a49f428a3c 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -707,7 +707,7 @@ todo-show
 				    shortf todo-show-first)))
 		     (when (eq todo-show-first 'regexp)
 		       (let ((rxfiles (directory-files todo-directory t
-						       ".*\\.todr$" t)))
+						       "\\.todr\\'" t)))
 			 (when (and rxfiles (> (length rxfiles) 1))
 			   (let ((rxf (mapcar #'todo-short-file-name rxfiles)))
 			     (setq fi-file (todo-absolute-file-name
@@ -4054,7 +4054,7 @@ todo--fifiles-history
 (defun todo-find-filtered-items-file ()
   "Choose a filtered items file and visit it."
   (interactive)
-  (let ((files (directory-files todo-directory t "\\.tod[rty]$" t))
+  (let ((files (directory-files todo-directory t "\\.tod[rty]\\'" t))
 	falist file)
     (dolist (f files)
       (let ((sf-name (todo-short-file-name f))
@@ -4187,7 +4187,7 @@ todo-filter-items
 				(regexp ".todr")))))
 	 (multi (> (length flist) 1))
 	 (rxfiles (when regexp
-		    (directory-files todo-directory t ".*\\.todr$" t)))
+		    (directory-files todo-directory t "\\.todr\\'" t)))
 	 (file-exists (or (file-exists-p fname) rxfiles))
 	 bufname)
     (cond ((and top new (natnump new))
@@ -6154,7 +6154,7 @@ todo-reset-nondiary-marker
   "The :set function for user option `todo-nondiary-marker'."
   (let* ((oldvalue (symbol-value symbol))
 	 (files (append todo-files todo-archives
-			(directory-files todo-directory t "\\.tod[rty]$" t))))
+			(directory-files todo-directory t "\\.tod[rty]\\'" t))))
     (custom-set-default symbol value)
     ;; Need to reset these to get font-locking right.
     (setq todo-nondiary-start (nth 0 todo-nondiary-marker)
@@ -6207,7 +6207,7 @@ todo-reset-done-string
   "The :set function for user option `todo-done-string'."
   (let ((oldvalue (symbol-value symbol))
 	(files (append todo-files todo-archives
-		       (directory-files todo-directory t "\\.todr$" t))))
+		       (directory-files todo-directory t "\\.todr\\'" t))))
     (custom-set-default symbol value)
     ;; Need to reset this to get font-locking right.
     (setq todo-done-string-start
@@ -6236,7 +6236,7 @@ todo-reset-comment-string
   "The :set function for user option `todo-comment-string'."
   (let ((oldvalue (symbol-value symbol))
   	(files (append todo-files todo-archives
-		       (directory-files todo-directory t "\\.todr$" t))))
+		       (directory-files todo-directory t "\\.todr\\'" t))))
     (custom-set-default symbol value)
     (when (not (equal value oldvalue))
       (dolist (f files)
@@ -6262,7 +6262,7 @@ todo-reset-highlight-item
   "The :set function for user option `todo-highlight-item'."
   (let ((oldvalue (symbol-value symbol))
 	(files (append todo-files todo-archives
-		       (directory-files todo-directory t "\\.tod[rty]$" t))))
+		       (directory-files todo-directory t "\\.tod[rty]\\'" t))))
     (custom-set-default symbol value)
     (when (not (equal value oldvalue))
       (dolist (f files)
diff --git a/lisp/cedet/semantic/db-ebrowse.el b/lisp/cedet/semantic/db-ebrowse.el
index 55e755dc36..a3219af7d3 100644
--- a/lisp/cedet/semantic/db-ebrowse.el
+++ b/lisp/cedet/semantic/db-ebrowse.el
@@ -181,7 +181,9 @@ semanticdb-load-ebrowse-caches
   "Load all semanticdb controlled EBROWSE caches."
   (interactive)
   (let ((f (directory-files semanticdb-default-save-directory
-			    t (concat semanticdb-ebrowse-default-file-name "-load.el$") t)))
+			    t (concat semanticdb-ebrowse-default-file-name
+                                      "-load\\.el\\'")
+                            t)))
     (while f
       (load (car f) nil t)
       (setq f (cdr f)))
diff --git a/lisp/cedet/semantic/texi.el b/lisp/cedet/semantic/texi.el
index 760cb19215..8e8d362ceb 100644
--- a/lisp/cedet/semantic/texi.el
+++ b/lisp/cedet/semantic/texi.el
@@ -495,7 +495,7 @@ semantic-texi-associated-files
 	       (setq tabs (cdr tabs)))
 	     r))
 	  (t
-	   (directory-files default-directory nil "\\.texi$"))
+	   (directory-files default-directory nil "\\.texi\\'"))
 	  )))
 
 ;; Turns out this might not be useful.
diff --git a/lisp/cedet/srecode/map.el b/lisp/cedet/srecode/map.el
index 784ebffe17..dc94920096 100644
--- a/lisp/cedet/srecode/map.el
+++ b/lisp/cedet/srecode/map.el
@@ -327,7 +327,7 @@ srecode-map-update-map
     ;; 4) - Find new files and add them to the map.
     (dolist (dir srecode-map-load-path)
       (when (file-exists-p dir)
-	(dolist (f (directory-files dir t "\\.srt$"))
+	(dolist (f (directory-files dir t "\\.srt\\'"))
 	  (when (and (not (backup-file-name-p f))
 		     (not (auto-save-file-name-p f))
 		     (file-readable-p f))
diff --git a/lisp/dired.el b/lisp/dired.el
index 689ad1fbfa..f2d478e83c 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -3171,7 +3171,7 @@ dired-recursive-deletes
   :group 'dired)
 
 ;; Match anything but `.' and `..'.
-(defvar dired-re-no-dot "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")
+(defvar dired-re-no-dot (rx (or (not ".") "...")))
 
 ;; Delete file, possibly delete a directory and all its files.
 ;; This function is useful outside of dired.  One could change its name
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index 785e350e0e..dc7461d93e 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -1047,7 +1047,7 @@ update-directory-autoloads
                        ;; what is the suffix for the underlying OS.
 		       (unless (string-match "\\.\\(elc\\|so\\|dll\\)" suf)
                          (push suf tmp)))
-                     (concat "^[^=.].*" (regexp-opt tmp t) "\\'")))
+                     (concat "\\`[^=.].*" (regexp-opt tmp t) "\\'")))
 	 (files (apply #'nconc
 		       (mapcar (lambda (dir)
 				 (directory-files (expand-file-name dir)
diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el
index f0a4870a69..4ff129e367 100644
--- a/lisp/emacs-lisp/shadow.el
+++ b/lisp/emacs-lisp/shadow.el
@@ -99,7 +99,8 @@ load-path-shadows-find
 	(setq true-names (append true-names (list dir)))
 	(setq dir (directory-file-name (or pp ".")))
 	(setq curr-files (if (file-accessible-directory-p dir)
-			     (directory-files dir nil ".\\.elc?\\(\\.gz\\)?$" t)))
+			     (directory-files dir nil
+                                              "\\.elc?\\(?:\\.gz\\)?\\'" t)))
 	(and curr-files
 	     (not noninteractive)
 	     (message "Checking %d files in %s..." (length curr-files) dir))
diff --git a/lisp/files.el b/lisp/files.el
index 01da2a985b..3e4ad7c0d4 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2671,7 +2671,7 @@ auto-mode-alist
      ("\\.pas\\'" . pascal-mode)
      ("\\.\\(dpr\\|DPR\\)\\'" . delphi-mode)
      ("\\.ad[abs]\\'" . ada-mode)
-     ("\\.ad[bs].dg\\'" . ada-mode)
+     ("\\.ad[bs]\\.dg\\'" . ada-mode)
      ("\\.\\([pP]\\([Llm]\\|erl\\|od\\)\\|al\\)\\'" . perl-mode)
      ("Imakefile\\'" . makefile-imake-mode)
      ("Makeppfile\\(?:\\.mk\\)?\\'" . makefile-makepp-mode) ; Put this before .mk
@@ -2822,7 +2822,7 @@ auto-mode-alist
      ("\\.properties\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-javaprop-mode)
      ("\\.toml\\'" . conf-toml-mode)
      ("\\.desktop\\'" . conf-desktop-mode)
-     ("/\\.redshift.conf\\'" . conf-windows-mode)
+     ("/\\.redshift\\.conf\\'" . conf-windows-mode)
      ("\\`/etc/\\(?:DIR_COLORS\\|ethers\\|.?fstab\\|.*hosts\\|lesskey\\|login\\.?de\\(?:fs\\|vperm\\)\\|magic\\|mtab\\|pam\\.d/.*\\|permissions\\(?:\\.d/.+\\)?\\|protocols\\|rpc\\|services\\)\\'" . conf-space-mode)
      ("\\`/etc/\\(?:acpid?/.+\\|aliases\\(?:\\.d/.+\\)?\\|default/.+\\|group-?\\|hosts\\..+\\|inittab\\|ksysguarddrc\\|opera6rc\\|passwd-?\\|shadow-?\\|sysconfig/.+\\)\\'" . conf-mode)
      ;; ChangeLog.old etc.  Other change-log-mode entries are above;
@@ -5754,7 +5754,7 @@ make-empty-file
   (write-region "" nil filename nil 0))
 
 (defconst directory-files-no-dot-files-regexp
-  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
+  "[^.]\\|\\.\\.\\."
   "Regexp matching any file name except \".\" and \"..\".")
 
 (defun files--force (no-such fn &rest args)
diff --git a/lisp/finder.el b/lisp/finder.el
index 96359b0b4f..71f8ac740e 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -188,7 +188,7 @@ finder-compile-keywords
   ;; Allow compressed files also.
   (setq package--builtins nil)
   (setq finder-keywords-hash (make-hash-table :test 'eq))
-  (let* ((el-file-regexp "^\\([^=].*\\)\\.el\\(\\.\\(gz\\|Z\\)\\)?$")
+  (let* ((el-file-regexp "\\`\\([^=].*\\)\\.el\\(\\.\\(gz\\|Z\\)\\)?\\'")
          (file-count 0)
          (files (cl-loop for d in (or dirs load-path)
                          when (file-exists-p (directory-file-name d))
diff --git a/lisp/generic-x.el b/lisp/generic-x.el
index d49193ccfc..cd24f497c9 100644
--- a/lisp/generic-x.el
+++ b/lisp/generic-x.el
@@ -1430,7 +1430,7 @@ inetd-conf-generic-mode
     "nowait"
     "internal")
   '(("^\\([-A-Za-z0-9_]+\\)" 1 font-lock-type-face))
-  '("/etc/inetd.conf\\'")
+  '("/etc/inetd\\.conf\\'")
   (list
    (function
     (lambda ()
@@ -1630,7 +1630,7 @@ named-boot-generic-mode
      (2 font-lock-variable-name-face)
      (3 font-lock-constant-face)))
   ;; List of additional automode-alist expressions
-  '("/etc/named.boot\\'")
+  '("/etc/named\\.boot\\'")
   ;; List of set up functions to call
   nil))
 
@@ -1667,7 +1667,7 @@ resolve-conf-generic-mode
   ;; List of additional font-lock-expressions
   nil
   ;; List of additional auto-mode-alist expressions
-  '("/etc/resolv[e]?.conf\\'")
+  '("/etc/resolve?\\.conf\\'")
   ;; List of set up functions to call
   nil))
 
@@ -1803,7 +1803,7 @@ etc-modules-conf-generic-mode
   ;; List of additional font-lock-expressions
   nil
   ;; List of additional automode-alist expressions
-  '("/etc/modules.conf" "/etc/conf.modules")
+  '("/etc/modules\\.conf" "/etc/conf\\.modules")
   ;; List of set up functions to call
   nil))
 
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 9f22b7df0f..cf705ae5dc 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -2074,7 +2074,7 @@ gnus-agent-read-agentview
 		  (file-attributes (directory-files-and-attributes
 				    (gnus-agent-article-name
 				     "" gnus-agent-read-agentview)
-				    nil "^[0-9]+$" t)))
+				    nil "\\`[0-9]+\\'" t)))
 	     (while file-attributes
 	       (let ((fa (pop file-attributes)))
 		 (unless (file-attribute-type (cdr fa))
@@ -3850,7 +3850,8 @@ gnus-agent-regenerate-group
 			   (sort (delq nil (mapcar (lambda (name)
 						     (and (not (file-directory-p (nnheader-concat dir name)))
 							  (string-to-number name)))
-						   (directory-files dir nil "^[0-9]+$" t)))
+						   (directory-files
+                                                    dir nil "\\`[0-9]+\\'" t)))
 				 '>)
 			 (progn (gnus-make-directory dir) nil)))
            nov-arts
@@ -4110,7 +4111,7 @@ gnus-agent-update-files-total-fetched-for
 		 (setq delta sum))
 	     (let ((sum (- (nth 2 entry)))
 		   (info (directory-files-and-attributes
-			  path nil "^-?[0-9]+$" t))
+			  path nil "\\`-?[0-9]+\\'" t))
 		   file)
 	       (while (setq file (pop info))
 		 (cl-incf sum (float (or (file-attribute-size (cdr file)) 0))))
diff --git a/lisp/gnus/gnus-cache.el b/lisp/gnus/gnus-cache.el
index 8b9acfe051..02a8ea723d 100644
--- a/lisp/gnus/gnus-cache.el
+++ b/lisp/gnus/gnus-cache.el
@@ -501,7 +501,7 @@ gnus-cache-articles-in-group
     (when (file-exists-p dir)
       (setq articles
 	    (sort (mapcar (lambda (name) (string-to-number name))
-			  (directory-files dir nil "^[0-9]+$" t))
+			  (directory-files dir nil "\\`[0-9]+\\'" t))
 		  '<))
       ;; Update the cache active file, just to synch more.
       (if articles
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index 41b63e2323..46b70eaf27 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -2981,7 +2981,7 @@ gnus-score-search-global-directories
       (if (file-directory-p (car files))
 	  (setq out (nconc (directory-files
 			    (car files) t
-			    (concat (gnus-score-file-regexp) "$"))))
+			    (concat (gnus-score-file-regexp) "\\'"))))
 	(push (car files) out))
       (setq files (cdr files)))
     (setq gnus-internal-global-score-files out)))
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index 23c62b4f93..3429d6560b 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -768,7 +768,7 @@ gnus-delete-directory
 If there's no subdirectory, delete DIRECTORY as well."
   (when (file-directory-p directory)
     (let ((files (directory-files
-		  directory t "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))
+		  directory t (rx (or (not ".") "..."))))
 	  file dir)
       (while files
 	(setq file (pop files))
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index d40ba9cef4..5902f2b37a 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -1674,7 +1674,7 @@ gnus-uu-treat-archive
     did-unpack))
 
 (defun gnus-uu-dir-files (dir)
-  (let ((dirs (directory-files dir t "[^/][^\\.][^\\.]?$"))
+  (let ((dirs (directory-files dir t (rx (or (not ".") "..."))))
 	files file)
     (while dirs
       (if (file-directory-p (setq file (car dirs)))
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index 3ee86a696c..a1337e8d7f 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -219,7 +219,7 @@ nndraft-request-group
       (nnheader-re-read-dir pathname)
       (setq dir (mapcar (lambda (name) (string-to-number (substring name 1)))
 			(ignore-errors (directory-files
-					pathname nil "^#[0-9]+#$" t))))
+					pathname nil "\\`#[0-9]+#\\'" t))))
       (dolist (n dir)
 	(unless (file-exists-p
 		 (setq file (expand-file-name (int-to-string n) pathname)))
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index c075f29898..8e7f0565e6 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -172,7 +172,7 @@ nnmh-request-group
 	(setq dir
 	      (sort
 	       (mapcar 'string-to-number
-		       (directory-files pathname nil "^[0-9]+$" t))
+		       (directory-files pathname nil "\\`[0-9]+\\'" t))
 	       '<))
 	(cond
 	 (dir
@@ -360,7 +360,7 @@ nnmh-request-create-group
       (nnmh-possibly-change-directory group server)
       (let ((articles (mapcar 'string-to-number
 			      (directory-files
-			       nnmh-current-directory nil "^[0-9]+$"))))
+			       nnmh-current-directory nil "\\`[0-9]+\\'"))))
 	(when articles
 	  (setcar active (apply 'min articles))
 	  (setcdr active (apply 'max articles))))))
@@ -371,7 +371,7 @@ nnmh-request-delete-group
   ;; Delete all articles in GROUP.
   (if (not force)
       ()				; Don't delete the articles.
-    (let ((articles (directory-files nnmh-current-directory t "^[0-9]+$")))
+    (let ((articles (directory-files nnmh-current-directory t "\\`[0-9]+\\'")))
       (while articles
 	(when (file-writable-p (car articles))
 	  (nnheader-message 5 "Deleting article %s in %s..."
@@ -485,7 +485,7 @@ nnmh-active-number
       ;; Find the highest number in the group.
       (let ((files (sort
 		    (mapcar 'string-to-number
-			    (directory-files dir nil "^[0-9]+$"))
+			    (directory-files dir nil "\\`[0-9]+\\'"))
 		    '>)))
 	(when files
 	  (setcdr active (car files)))))
@@ -509,7 +509,7 @@ nnmh-update-gnus-unreads
   (let* ((dir nnmh-current-directory)
 	 (files (sort (mapcar 'string-to-number
 			      (directory-files nnmh-current-directory
-					       nil "^[0-9]+$" t))
+					       nil "\\`[0-9]+\\'" t))
 		      '<))
 	 (nnmh-file (concat dir ".nnmh-articles"))
 	 new articles)
diff --git a/lisp/gnus/nnspool.el b/lisp/gnus/nnspool.el
index da13a56001..33b68fa989 100644
--- a/lisp/gnus/nnspool.el
+++ b/lisp/gnus/nnspool.el
@@ -260,7 +260,7 @@ nnspool-request-group
 	    t)
 	;; Yes, completely empty spool directories *are* possible.
 	;; Fix by Sudish Joseph <joseph@cis.ohio-state.edu>
-	(when (setq dir (directory-files pathname nil "^[0-9]+$" t))
+	(when (setq dir (directory-files pathname nil "\\`[0-9]+\\'" t))
 	  (setq dir (sort (mapcar 'string-to-number dir) '<)))
 	(if dir
 	    (nnheader-insert
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index 2e03608b5d..3da45a2b62 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -557,7 +557,7 @@ spam-stat-strip-xref
 
 (defun spam-stat-process-directory (dir func)
   "Process all the regular files in directory DIR using function FUNC."
-  (let* ((files (directory-files dir t "^[^.]"))
+  (let* ((files (directory-files dir t "\\`[^.]"))
 	 (max (/ (length files) 100.0))
 	 (count 0))
     (with-temp-buffer
@@ -601,7 +601,7 @@ spam-stat-test-directory
 non-spam in a temporary buffer.  If it is the symbol `ham',
 display non-spam files; otherwise display spam files."
   (interactive "DDirectory: ")
-  (let* ((files (directory-files dir t "^[^.]"))
+  (let* ((files (directory-files dir t "\\`[^.]"))
 	 display-files
 	 buffer-score
 	 (total (length files))
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 1be8e0ab08..c7d0112cb6 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -623,7 +623,7 @@ help-fns--first-release
   ;; of the *packages* in which the function is defined.
   (let* ((name (symbol-name symbol))
          (re (concat "\\_<" (regexp-quote name) "\\_>"))
-         (news (directory-files data-directory t "\\`NEWS.[1-9]"))
+         (news (directory-files data-directory t "\\`NEWS\\.[1-9]"))
          (place nil)
          (first nil))
     (with-temp-buffer
diff --git a/lisp/help.el b/lisp/help.el
index 45cbaad4e8..0f1991e318 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -361,7 +361,7 @@ view-emacs-news
 		     (setq res (cons (match-string-no-properties 1) res)))))
 	       (cons "NEWS"
 		     (directory-files data-directory nil
-				      "^NEWS\\.[0-9][-0-9]*$" nil)))
+				      "\\`NEWS\\.[0-9][-0-9]*\\'" nil)))
 	      (sort (delete-dups res) #'string>)))
 	   (current (car all-versions)))
       (setq version (completing-read
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 193b1d7c2c..3299cc55a2 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -3059,7 +3059,7 @@ quail-update-leim-list-file
     (while quail-dirs
       (setq dirname (car quail-dirs))
       (when dirname
-	(setq pkg-list (directory-files dirname 'full "\\.el$"))
+	(setq pkg-list (directory-files dirname 'full "\\.el\\'"))
 	(while pkg-list
 	  (with-temp-buffer
 	    (insert-file-contents (car pkg-list))
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index 2a80d75fe7..4f1bcf2f94 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -553,7 +553,7 @@ batch-titdic-convert
 	(if (file-directory-p filename)
 	    (progn
 	      (message "Converting all tit files in the directory %s" filename)
-	      (setq files (directory-files filename t "\\.tit$")))
+	      (setq files (directory-files filename t "\\.tit\\'")))
 	  (setq files (list filename)))
 	(while files
 	  (setq file (expand-file-name (car files)))
diff --git a/lisp/mail/mspools.el b/lisp/mail/mspools.el
index 9c0c3fe5ca..94b0886c75 100644
--- a/lisp/mail/mspools.el
+++ b/lisp/mail/mspools.el
@@ -223,7 +223,7 @@ mspools-set-vm-spool-files
 	    ;; So I create a vm-spool-files entry for each of those mail drops
 	    (mapcar 'file-name-sans-extension
 		    (directory-files mspools-folder-directory nil
-				     (format "^[^.]+\\.%s" mspools-suffix)))
+				     (format "\\`[^.]+\\.%s" mspools-suffix)))
 	    ))
    ))
 
@@ -357,7 +357,7 @@ mspools-get-spool-files
     (if (null mspools-folder-directory)
 	(error "Set `mspools-folder-directory' to where the spool files are"))
     (setq folders (directory-files mspools-folder-directory nil
-				   (format "^[^.]+\\.%s$" mspools-suffix)))
+				   (format "\\`[^.]+\\.%s\\'" mspools-suffix)))
     (setq folders (mapcar 'mspools-size-folder folders))
     (setq folders (delq nil folders))
     (setq mspools-files folders)
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index d798ffa051..3feff803e3 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -474,7 +474,7 @@ rmail-secondary-file-directory
   :type 'directory
   :group 'rmail-files)
 ;;;###autoload
-(defcustom rmail-secondary-file-regexp (purecopy "\\.xmail$")
+(defcustom rmail-secondary-file-regexp (purecopy "\\.xmail\\'")
   "Regexp for which files are secondary Rmail files."
   :type 'regexp
   :group 'rmail-files)
@@ -4354,7 +4354,8 @@ rmail-fontify-message
 	    (font-lock-fontify-region (point-min) (point-max)))))))
 \f
 ;;; Speedbar support for RMAIL files.
-(defcustom rmail-speedbar-match-folder-regexp "^[A-Z0-9]+\\(\\.[A-Z0-9]+\\)?$"
+(defcustom rmail-speedbar-match-folder-regexp
+  "\\`[A-Z0-9]+\\(\\.[A-Z0-9]+\\)?\\'"
   "Regexp matching Rmail folder names to be displayed in Speedbar.
 Enabling this permits Speedbar to display your folders for easy
 browsing, and moving of messages."
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 1d45604490..92ed98b2a8 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -4170,8 +4170,7 @@ ange-ftp-delete-directory
 		   (ange-ftp-delete-directory file recursive trash)
 		 (delete-file file trash)))
 	     ;; We do not want to delete "." and "..".
-	     (directory-files
-	      dir 'full "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")))
+	     (directory-files dir 'full (rx (or (not ".") "...")))))
 	(if parsed
 	    (let* ((host (nth 0 parsed))
 		   (user (nth 1 parsed))
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 0ad65fb8bd..4f3249d966 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2458,7 +2458,7 @@ tramp-use-absolute-autoload-file-names
 	   (regexp-opt
 	    (mapcar
 	     #'file-name-sans-extension
-	     (directory-files dir nil "^tramp.+\\.elc?$"))
+	     (directory-files dir nil "\\`tramp.+\\.elc?\\'"))
 	    'paren))))
     (mapatoms
      (lambda (atom)
diff --git a/lisp/obsolete/gulp.el b/lisp/obsolete/gulp.el
index 6589ede69d..08ab3884d4 100644
--- a/lisp/obsolete/gulp.el
+++ b/lisp/obsolete/gulp.el
@@ -94,7 +94,7 @@ gulp-send-requests
   (interactive "DRequest updates for Lisp directory: \nP")
   (with-current-buffer (get-buffer-create gulp-tmp-buffer)
     (let ((m-p-alist (gulp-create-m-p-alist
-		      (directory-files dir nil "^[^=].*\\.el$" t)
+		      (directory-files dir nil "\\`[^=].*\\.el\\'" t)
 		      dir))
 	  ;; Temporarily inhibit undo in the *gulp* buffer.
 	  (buffer-undo-list t)
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index b186a5c52a..bcdefac518 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -597,18 +597,20 @@ vc-arch-trim-revlib
     (unless (file-writable-p rl-dir)
       (error "No writable revlib directory found"))
     (message "Revlib at %s" rl-dir)
-    (let* ((archives (directory-files rl-dir 'full "[^.]\\|..."))
+    (let* ((archives (directory-files rl-dir 'full (rx (or (not ".") "..."))))
            (categories
             (apply 'append
                    (mapcar (lambda (dir)
                              (when (file-directory-p dir)
-                               (directory-files dir 'full "[^.]\\|...")))
+                               (directory-files dir 'full
+                                                (rx (or (not ".") "...")))))
                            archives)))
            (branches
             (apply 'append
                    (mapcar (lambda (dir)
                              (when (file-directory-p dir)
-                               (directory-files dir 'full "[^.]\\|...")))
+                               (directory-files dir 'full
+                                                (rx (or (not ".") "...")))))
                            categories)))
            (versions
             (apply 'append
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 651561a201..7654c7ebe4 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -3055,7 +3055,7 @@ org-babel-remove-temporary-directory
 		    (delete-file file)))
 		;; We do not want to delete "." and "..".
 		(directory-files org-babel-temporary-directory 'full
-				 "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))
+                                 (rx (or (not ".") "..."))))
 	  (delete-directory org-babel-temporary-directory))
       (error
        (message "Failed to remove temporary Org-babel directory %s"
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index d5820bbfe0..640cb576ef 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -1898,7 +1898,7 @@ ebnf-iso-normalize-p
   :group 'ebnf-syntactic)
 
 
-(defcustom ebnf-file-suffix-regexp "\\.[Bb][Nn][Ff]$"
+(defcustom ebnf-file-suffix-regexp "\\.[Bb][Nn][Ff]\\'"
   "Specify file name suffix that contains EBNF.
 
 See `ebnf-eps-directory' command."
@@ -2731,7 +2731,7 @@ ebnf-style-database
       (ebnf-syntax                      . 'ebnf)
       (ebnf-iso-alternative-p           . nil)
       (ebnf-iso-normalize-p             . nil)
-      (ebnf-file-suffix-regexp          . "\\.[Bb][Nn][Ff]$")
+      (ebnf-file-suffix-regexp          . "\\.[Bb][Nn][Ff]\\'")
       (ebnf-eps-prefix                  . "ebnf--")
       (ebnf-eps-header-font             . '(11 Helvetica "Black" "White" bold))
       (ebnf-eps-header                  . nil)
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index b42e6f73ab..bae2bb6640 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -155,7 +155,7 @@ executable-command-find-posix-p
 If PROGRAM is non-nil, use that instead of \"find\"."
   ;;  Pick file to search from location we know
   (let* ((dir (file-truename data-directory))
-         (file (car (directory-files dir nil "^[^.]"))))
+         (file (car (directory-files dir nil "\\`[^.]"))))
     (with-temp-buffer
       (call-process (or program "find")
                     nil
diff --git a/lisp/startup.el b/lisp/startup.el
index 1f545c6692..5af264e3ef 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1373,10 +1373,10 @@ command-line
         ((not (eq system-type 'windows-nt))
          (concat "~" init-file-user "/.emacs"))
         ;; Else deal with the Windows situation.
-        ((directory-files "~" nil "^\\.emacs\\(\\.elc?\\)?$")
+        ((directory-files "~" nil "\\`\\.emacs\\(\\.elc?\\)?\\'")
          ;; Prefer .emacs on Windows.
          "~/.emacs")
-        ((directory-files "~" nil "^_emacs\\(\\.elc?\\)?$")
+        ((directory-files "~" nil "\\`_emacs\\(\\.elc?\\)?\\'")
          ;; Also support _emacs for compatibility, but warn about it.
          (push `(initialization
                  ,(format-message
diff --git a/lisp/textmodes/refer.el b/lisp/textmodes/refer.el
index 2865b42273..8d8223a732 100644
--- a/lisp/textmodes/refer.el
+++ b/lisp/textmodes/refer.el
@@ -377,7 +377,7 @@ refer-get-bib-files
                    dir files)
                (while (setq dir (car dirs))
                  (setq files
-                       (append (directory-files dir t "\\.bib$")
+                       (append (directory-files dir t "\\.bib\\'")
                                files))
                  (setq dirs (cdr dirs)))
                files))
diff --git a/lisp/url/url-about.el b/lisp/url/url-about.el
index fd83ac3436..dde47e94de 100644
--- a/lisp/url/url-about.el
+++ b/lisp/url/url-about.el
@@ -37,7 +37,7 @@ url-probe-protocols
 			  (mapc (lambda (f)
 				  (if (string-match "url-\\(.*\\).el$" f)
 				      (push (match-string 1 f) schemes)))
-				(directory-files d nil "^url-.*\\.el$")))
+				(directory-files d nil "\\`url-.*\\.el\\'")))
 			load-path)
 		  (put 'url-extension-protocols 'schemes schemes)
 		  schemes)))))
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index 00796e5d63..273f37c10d 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -247,7 +247,7 @@ vc-rcs-register
 		 (setq subdir (expand-file-name "RCS"
 						(file-name-directory file)))))
 	   (not (directory-files (file-name-directory file)
-				 nil ".*,v$" t))
+				 nil ",v\\'" t))
 	   (yes-or-no-p "Create RCS subdirectory? ")
 	   (make-directory subdir))
       (apply #'vc-do-command "*vc*" 0 "ci" file
@@ -312,8 +312,7 @@ vc-rcs-unregister
       (and (string= (file-name-nondirectory (directory-file-name dir)) "RCS")
 	   ;; check whether RCS dir is empty, i.e. it does not
 	   ;; contain any files except "." and ".."
-	   (not (directory-files dir nil
-				 "^\\([^.]\\|\\.[^.]\\|\\.\\.[^.]\\).*"))
+	   (not (directory-files dir nil (rx (or (not ".") "..."))))
 	   (yes-or-no-p (format "Directory %s is empty; remove it? " dir))
 	   (delete-directory dir)))))
 
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el
index 3229d2b650..95e41a3f03 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -669,7 +669,7 @@ tramp-archive-test19-directory-files-and-attributes
 	  (setq attr (directory-files-and-attributes tmp-name 'full))
 	  (dolist (elt attr)
 	    (should (equal (file-attributes (car elt)) (cdr elt))))
-	  (setq attr (directory-files-and-attributes tmp-name nil "^b"))
+	  (setq attr (directory-files-and-attributes tmp-name nil "\\`b"))
 	  (should (equal (mapcar #'car attr) '("bar"))))
 
       ;; Cleanup.
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 47d51767c5..544bdb5c05 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -3331,7 +3331,7 @@ tramp-test19-directory-files-and-attributes
 	       (tramp--test-file-attributes-equal-p
 		(file-attributes (car elt)) (cdr elt))))
 
-	    (setq attr (directory-files-and-attributes tmp-name2 nil "^b"))
+	    (setq attr (directory-files-and-attributes tmp-name2 nil "\\`b"))
 	    (should (equal (mapcar #'car attr) '("bar" "boz"))))
 
 	;; Cleanup.

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-14 10:52 ` Mattias Engdegård
@ 2020-04-14 11:15   ` Andreas Schwab
  2020-04-16 10:15     ` Mattias Engdegård
  2020-04-14 15:47   ` Drew Adams
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Andreas Schwab @ 2020-04-14 11:15 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: emacs-devel

On Apr 14 2020, Mattias Engdegård wrote:

> diff --git a/lisp/cedet/semantic/db-ebrowse.el b/lisp/cedet/semantic/db-ebrowse.el
> index 55e755dc36..a3219af7d3 100644
> --- a/lisp/cedet/semantic/db-ebrowse.el
> +++ b/lisp/cedet/semantic/db-ebrowse.el
> @@ -181,7 +181,9 @@ semanticdb-load-ebrowse-caches
>    "Load all semanticdb controlled EBROWSE caches."
>    (interactive)
>    (let ((f (directory-files semanticdb-default-save-directory
> -			    t (concat semanticdb-ebrowse-default-file-name "-load.el$") t)))
> +			    t (concat semanticdb-ebrowse-default-file-name

I think that needs to regexp-quote semanticdb-ebrowse-default-file-name.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Scan of Emacs regexp mistakes
  2020-04-14 10:52 ` Mattias Engdegård
  2020-04-14 11:15   ` Andreas Schwab
@ 2020-04-14 15:47   ` Drew Adams
  2020-04-15 18:19   ` Paul Eggert
  2020-04-16 10:37   ` Mattias Engdegård
  3 siblings, 0 replies; 10+ messages in thread
From: Drew Adams @ 2020-04-14 15:47 UTC (permalink / raw)
  To: Mattias Engdegård, emacs-devel

> The filename-matching regexp glitches were fixed separately by the
> attached patch, pushed to emacs-27, since these were actual or latent
> bugs.
> 
> Several different regexps were used for matching anything but "." and
> "..", all wrong. These were all replaced with the concise and correct
> (rx (or (not ".") "...")), meaning "[^.]\\|\\.\\.\\." for
> traditionalists.
> 
> It is quite clear that returning . and .. from directory-files etc was
> a mistake; they are practically never useful but requires callers to
> take steps to filter them out. It's likely that nothing would break if
> we stopped returning those entries, but that is not a change that I'm
> proposing right now.

FWIW -

That "quite clear" is not clear to me.

And it's not clear to me why you think "[^.]\\|\\.\\.\\."
is more correct than "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*",
which is what Dired has used for a file name other than `.'
and `..'.

This kind of wholescale changing of regexps seems unwise,
to me.  Who knows how long it will take for each of the
changes to actually be checked in practice, to see
whether it is an improvement or breaks things?

The changes from ^ ... $ to \\` ... \\' are probably
good, or at least OK (no, I didn't check them
individually).  But the filename-except-.-or-.. change
seems wrong, in general.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-14 10:52 ` Mattias Engdegård
  2020-04-14 11:15   ` Andreas Schwab
  2020-04-14 15:47   ` Drew Adams
@ 2020-04-15 18:19   ` Paul Eggert
  2020-04-16 10:29     ` Mattias Engdegård
  2020-04-16 10:37   ` Mattias Engdegård
  3 siblings, 1 reply; 10+ messages in thread
From: Paul Eggert @ 2020-04-15 18:19 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: emacs-devel

On 4/14/20 3:52 AM, Mattias Engdegård wrote:

>  (defvar authors-obsolete-files-regexps
> -  '(".*loaddefs.el$"			; not obsolete, but auto-generated
> +  '(".*loaddefs\\.el$"			; not obsolete, but auto-generated
>      "\\.\\(bzr\\|cvs\\|git\\)ignore$"		; obsolete or uninteresting
>      "\\.arch-inventory$"

Should those trailing "$"s be changed to "\\'"s?

>  ;; Match anything but `.' and `..'.
> -(defvar dired-re-no-dot "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")
> +(defvar dired-re-no-dot (rx (or (not ".") "...")))
...
>  (defconst directory-files-no-dot-files-regexp
> -  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
> +  "[^.]\\|\\.\\.\\."
>    "Regexp matching any file name except \".\" and \"..\".")

We shouldn't have two names for the same variable. I suggest obsoleting 
dired-re-no-dot and replacing its only use with directory-files-no-dot-files-regexp.

As Drew's comments make evident, the doc string is unclear.  It should be 
something like 'Regexp that matches part of a nonempty string if the string is 
neither "." nor "..".'

>      (let ((files (directory-files
> -		  directory t "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))
> +		  directory t (rx (or (not ".") "..."))))

Shouldn't this and similar uses of (rx (or (not ".") "...")) be replaced by 
directory-files-no-dot-files-regexp?  That would be clearer.

I agree with you that directory-files should not return "." and "..", though 
that indeed is a different topic.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-14 11:15   ` Andreas Schwab
@ 2020-04-16 10:15     ` Mattias Engdegård
  0 siblings, 0 replies; 10+ messages in thread
From: Mattias Engdegård @ 2020-04-16 10:15 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: emacs-devel

14 apr. 2020 kl. 13.15 skrev Andreas Schwab <schwab@linux-m68k.org>:

> I think that needs to regexp-quote semanticdb-ebrowse-default-file-name.

Thanks Andreas! Fixed on master.




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-15 18:19   ` Paul Eggert
@ 2020-04-16 10:29     ` Mattias Engdegård
  0 siblings, 0 replies; 10+ messages in thread
From: Mattias Engdegård @ 2020-04-16 10:29 UTC (permalink / raw)
  To: Paul Eggert; +Cc: emacs-devel

15 apr. 2020 kl. 20.19 skrev Paul Eggert <eggert@cs.ucla.edu>:

> Should those trailing "$"s be changed to "\\'"s?

Thanks, now fixed. (Those weren't caught by relint but by manual inspection, hence the unfinished work.)

> We shouldn't have two names for the same variable. I suggest obsoleting dired-re-no-dot and replacing its only use with directory-files-no-dot-files-regexp.

Yes; the initial changes were deliberately limited in scope.

> As Drew's comments make evident, the doc string is unclear.  It should be something like 'Regexp that matches part of a nonempty string if the string is neither "." nor "..".'

A clarification has been added, and a note about the intended use.

> Shouldn't this and similar uses of (rx (or (not ".") "...")) be replaced by directory-files-no-dot-files-regexp?  That would be clearer.

Very much so.
All done on master.

> I agree with you that directory-files should not return "." and "..", though that indeed is a different topic.

Seems to be a common syndrome in older runtimes (Emacs Lisp, Perl), absent in newer ones (OCaml, Python).




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-14 10:52 ` Mattias Engdegård
                     ` (2 preceding siblings ...)
  2020-04-15 18:19   ` Paul Eggert
@ 2020-04-16 10:37   ` Mattias Engdegård
  2020-04-16 16:08     ` Paul Eggert
  3 siblings, 1 reply; 10+ messages in thread
From: Mattias Engdegård @ 2020-04-16 10:37 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 492 bytes --]

The remaining regexp glitches found by the latest sweep were fixed by the attached patch (now on master), except tramp-adb-prompt:

lisp/net/tramp-adb.el:59:56: In tramp-adb-prompt: Repetition subsumes preceding repetition (pos 50)
  "^[[:digit:]]*|?[[:alnum:]\e;[]*@?[[:alnum:]]*[^#\\$]*[#\\$][[:space:]]"
   ....................................................^

I think it should be "^[^#$\n]*[#$] ", but hold out for some assistance from the author (Jürgen Hötzel, contacted).


[-- Attachment #2: 0001-Fix-bugs-inefficiencies-and-bad-style-in-regexps.patch --]
[-- Type: application/octet-stream, Size: 7749 bytes --]

From 905c0a13f7929298cb36151f46dbef03f7bdcbe4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Thu, 16 Apr 2020 11:04:24 +0200
Subject: [PATCH] Fix bugs, inefficiencies and bad style in regexps

Found by relint.  See discussion at
https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg00265.html

* lisp/org/org-table.el (org-table-finish-edit-field):
* lisp/arc-mode.el (archive-rar-summarize):
Avoid wrapped subsumption in repeated sequences.
* lisp/erc/erc-dcc.el (erc-dcc-ctcp-query-send-regexp): Replace
inefficient repeated empty-matching expression with a plain greedy
form.
(erc-dcc-handle-ctcp-send): Adjust group numbers.
* lisp/net/puny.el (puny-encode-domain): Fix fast-path shortcut
pattern so that it actually works as intended.
* lisp/progmodes/gdb-mi.el (gdb-control-commands-regexp):
* lisp/vc/diff-mode.el (diff-imenu-generic-expression):
Remove superfluous backslashes.
* lisp/progmodes/scheme.el (scheme-imenu-generic-expression):
Correct confused definition-matching pattern which would match more
than intended.
* lisp/textmodes/sgml-mode.el (sgml-tag-name-re): Avoid inefficient
matching by using the fact that the first character cannot match the
last char of sgml-name-re.
---
 lisp/arc-mode.el            |  2 +-
 lisp/erc/erc-dcc.el         | 14 +++++++-------
 lisp/net/puny.el            |  2 +-
 lisp/org/org-table.el       |  2 +-
 lisp/progmodes/gdb-mi.el    |  2 +-
 lisp/progmodes/scheme.el    |  2 +-
 lisp/textmodes/sgml-mode.el |  5 ++++-
 lisp/vc/diff-mode.el        |  2 +-
 8 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 4d36667969..c918f06c80 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -2032,7 +2032,7 @@ archive-rar-summarize
           (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")
+      (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
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index 26701cec1e..8ccceec459 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -627,11 +627,11 @@ erc-ctcp-query-DCC
        ?q query ?n nick ?u login ?h host))))
 
 (defconst erc-dcc-ctcp-query-send-regexp
-  (concat "^DCC SEND \\("
+  (concat "^DCC SEND \\(?:"
           ;; Following part matches either filename without spaces
           ;; or filename enclosed in double quotes with any number
           ;; of escaped double quotes inside.
-          "\"\\(\\(.*?\\(\\\\\"\\)?\\)+?\\)\"\\|\\([^ ]+\\)"
+          "\"\\(\\(?:\\\\\"\\|[^\"\\]\\)+\\)\"\\|\\([^ ]+\\)"
           "\\) \\([0-9]+\\) \\([0-9]+\\) *\\([0-9]*\\)"))
 
 (define-inline erc-dcc-unquote-filename (filename)
@@ -653,11 +653,11 @@ erc-dcc-handle-ctcp-send
        ?r "SEND" ?n nick ?u login ?h host))
      ((string-match erc-dcc-ctcp-query-send-regexp query)
       (let ((filename
-             (or (match-string 5 query)
-                 (erc-dcc-unquote-filename (match-string 2 query))))
-            (ip       (erc-decimal-to-ip (match-string 6 query)))
-            (port     (match-string 7 query))
-            (size     (match-string 8 query)))
+             (or (match-string 2 query)
+                 (erc-dcc-unquote-filename (match-string 1 query))))
+            (ip       (erc-decimal-to-ip (match-string 3 query)))
+            (port     (match-string 4 query))
+            (size     (match-string 5 query)))
         ;; FIXME: a warning really should also be sent
         ;; if the ip address != the host the dcc sender is on.
         (erc-display-message
diff --git a/lisp/net/puny.el b/lisp/net/puny.el
index 60a6c12e6c..6987d25324 100644
--- a/lisp/net/puny.el
+++ b/lisp/net/puny.el
@@ -35,7 +35,7 @@ puny-encode-domain
 For instance, \"fśf.org\" => \"xn--ff-2sa.org\"."
   ;; The vast majority of domain names are not IDNA domain names, so
   ;; add a check first to avoid doing unnecessary work.
-  (if (string-match "\\'[[:ascii:]]+\\'" domain)
+  (if (string-match "\\`[[:ascii:]]+\\'" domain)
       domain
     (mapconcat 'puny-encode-string (split-string domain "[.]") ".")))
 
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 98702feb37..8927b1c2ed 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -2005,7 +2005,7 @@ org-table-finish-edit-field
 	text)
     (goto-char (point-min))
     (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
-    (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
+    (while (re-search-forward "[ \t]*\\(?:\n[ \t]*\\)+" nil t)
       (replace-match " "))
     (setq text (org-trim (buffer-string)))
     (set-window-configuration cw)
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index ba586981de..c1184211d0 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1867,7 +1867,7 @@ gdb-control-commands-regexp
    "\\|def\\(i\\(ne?\\)?\\)?\\|doc\\(u\\(m\\(e\\(nt?\\)?\\)?\\)?\\)?\\|"
    gdb-python-guile-commands-regexp
    "\\|while-stepping\\|stepp\\(i\\(ng?\\)?\\)?\\|ws\\|actions"
-   "\\|expl\\(o\\(r\\e?\\)?\\)?"
+   "\\|expl\\(o\\(re?\\)?\\)?"
    "\\)\\([[: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
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index 751d7da542..33ba0d11d8 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -116,7 +116,7 @@ 'scheme-mode-abbrev-table
 
 (defvar scheme-imenu-generic-expression
       '((nil
-         "^(define\\(\\|-\\(generic\\(\\|-procedure\\)\\|method\\)\\)*\\s-+(?\\(\\sw+\\)" 4)
+         "^(define\\(?:-\\(?:generic\\(?:-procedure\\)?\\|method\\)\\)?\\s-+(?\\(\\sw+\\)" 1)
         ("Types"
          "^(define-class\\s-+(?\\(\\sw+\\)" 1)
         ("Macros"
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 6152a8ad0a..9b29b844d0 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -286,7 +286,10 @@ sgml-slash-distance
 (defconst sgml-namespace-re "[_[:alpha:]][-_.[:alnum:]]*")
 (defconst sgml-name-re "[_:[:alpha:]][-_.:[:alnum:]]*")
 (defconst sgml-tag-name-re (concat "<\\([!/?]?" sgml-name-re "\\)"))
-(defconst sgml-attrs-re "\\(?:[^\"'/><]\\|\"[^\"]*\"\\|'[^']*'\\)*")
+(defconst sgml-attrs-re
+  ;; This pattern cannot begin with a character matched by the end of
+  ;; `sgml-name-re' above.
+  "\\(?:[^_.:\"'/><[:alnum:]-]\\(?:[^\"'/><]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?")
 (defconst sgml-start-tag-regex (concat "<" sgml-name-re sgml-attrs-re)
   "Regular expression that matches a non-empty start tag.
 Any terminating `>' or `/' is not matched.")
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index da2d5ed50e..d194d6c0a0 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -484,7 +484,7 @@ diff-imenu-generic-expression
   ;; Prefer second name as first is most likely to be a backup or
   ;; version-control name.  The [\t\n] at the end of the unidiff pattern
   ;; catches Debian source diff files (which lack the trailing date).
-  '((nil "\\+\\+\\+\\ \\([^\t\n]+\\)[\t\n]" 1) ; unidiffs
+  '((nil "\\+\\+\\+ \\([^\t\n]+\\)[\t\n]" 1) ; unidiffs
     (nil "^--- \\([^\t\n]+\\)\t.*\n\\*" 1))) ; context diffs
 
 ;;;;
-- 
2.21.1 (Apple Git-122.3)


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-16 10:37   ` Mattias Engdegård
@ 2020-04-16 16:08     ` Paul Eggert
  2020-04-16 18:01       ` Mattias Engdegård
  0 siblings, 1 reply; 10+ messages in thread
From: Paul Eggert @ 2020-04-16 16:08 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: emacs-devel

On 4/16/20 3:37 AM, Mattias Engdegård wrote:
> The remaining regexp glitches found by the latest sweep were fixed by the attached patch (now on master), except tramp-adb-prompt:

Thanks. One little question:

> -    (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
> +    (while (re-search-forward "[ \t]*\\(?:\n[ \t]*\\)+" nil t)
>        (replace-match " "))

Wouldn't it be better to use "[ \t]*\n[ \t\n]*"?



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Scan of Emacs regexp mistakes
  2020-04-16 16:08     ` Paul Eggert
@ 2020-04-16 18:01       ` Mattias Engdegård
  0 siblings, 0 replies; 10+ messages in thread
From: Mattias Engdegård @ 2020-04-16 18:01 UTC (permalink / raw)
  To: Paul Eggert; +Cc: emacs-devel

16 apr. 2020 kl. 18.08 skrev Paul Eggert <eggert@cs.ucla.edu>:

>> -    (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
>> +    (while (re-search-forward "[ \t]*\\(?:\n[ \t]*\\)+" nil t)
>>       (replace-match " "))
> 
> Wouldn't it be better to use "[ \t]*\n[ \t\n]*"?

Superior in every way, thank you! Evidenced by disassembling them: your pattern results in both loops being optimised, compared to only the first (of three) in my clumsy attempt.




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-04-16 18:01 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-05 12:30 Scan of Emacs regexp mistakes Mattias Engdegård
2020-04-14 10:52 ` Mattias Engdegård
2020-04-14 11:15   ` Andreas Schwab
2020-04-16 10:15     ` Mattias Engdegård
2020-04-14 15:47   ` Drew Adams
2020-04-15 18:19   ` Paul Eggert
2020-04-16 10:29     ` Mattias Engdegård
2020-04-16 10:37   ` Mattias Engdegård
2020-04-16 16:08     ` Paul Eggert
2020-04-16 18:01       ` Mattias Engdegård

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).